Browse Source

Keeping a list of all active windows
Some GUIManager work to keep track of all windows and window in focus

Marko Pintera 12 years ago
parent
commit
427fdce2ce

+ 19 - 0
BansheeEngine/Include/BsGUIManager.h

@@ -3,6 +3,8 @@
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
 #include "CmModule.h"
 #include "CmModule.h"
 
 
+#include "boost/signals/connection.hpp"
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	/**
 	/**
@@ -11,10 +13,27 @@ namespace BansheeEngine
 	class BS_EXPORT GUIManager : public CM::Module<GUIManager>
 	class BS_EXPORT GUIManager : public CM::Module<GUIManager>
 	{
 	{
 	public:
 	public:
+		GUIManager();
+		~GUIManager();
+
 		void registerWidget(GUIWidget* widget);
 		void registerWidget(GUIWidget* widget);
 		void unregisterWidget(GUIWidget* widget);
 		void unregisterWidget(GUIWidget* widget);
 
 
+		/**
+		 * @brief	Attaches a widget to a window. One widget can be attached to multiple input. Calling this
+		 * 			guarantees that the widget will receieve any input received by the window.
+		 */
+		void attachWidgetToWindow(const CM::RenderWindow* window, GUIWidget* widget);
+
+		void update();
 	private:
 	private:
+		boost::signals::connection windowCreateConn;
+		boost::signals::connection windowDestroyConn;
+
 		std::vector<GUIWidget*> mWidgets;
 		std::vector<GUIWidget*> mWidgets;
+		std::unordered_map<const CM::RenderWindow*, std::vector<GUIWidget*>> mInputMap;
+
+		void doOnWindowCreated(CM::RenderWindow* window);
+		void doOnWindowDestroyed(CM::RenderWindow* window);
 	};
 	};
 }
 }

+ 68 - 0
BansheeEngine/Source/BsGUIManager.cpp

@@ -5,9 +5,25 @@
 #include "CmMeshData.h"
 #include "CmMeshData.h"
 #include "CmMesh.h"
 #include "CmMesh.h"
 #include "CmUtil.h"
 #include "CmUtil.h"
+#include "CmRenderWindowManager.h"
+#include "CmException.h"
+
+using namespace CamelotFramework;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	GUIManager::GUIManager()
+	{
+		//windowCreateConn = RenderWindowManager::instance().onWindowCreated.connect(boost::bind(&GUIManager::doOnWindowCreated, this, _1));
+		//windowDestroyConn = RenderWindowManager::instance().onWindowDestroyed.connect(boost::bind(&GUIManager::doOnWindowDestroyed, this, _1));
+	}
+
+	GUIManager::~GUIManager()
+	{
+		//RenderWindowManager::instance().onWindowCreated.disconnect(windowCreateConn);
+		//RenderWindowManager::instance().onWindowDestroyed.disconnect(windowDestroyConn);
+	}
+
 	void GUIManager::registerWidget(GUIWidget* widget)
 	void GUIManager::registerWidget(GUIWidget* widget)
 	{
 	{
 		mWidgets.push_back(widget);
 		mWidgets.push_back(widget);
@@ -19,5 +35,57 @@ namespace BansheeEngine
 
 
 		if(findIter != end(mWidgets))
 		if(findIter != end(mWidgets))
 			mWidgets.erase(findIter);
 			mWidgets.erase(findIter);
+
+		for(auto& windowMap : mInputMap)
+		{
+			auto& widgets = windowMap.second;
+			auto iterFind = std::find(begin(widgets), end(widgets), widget);
+
+			if(iterFind != end(widgets))
+				widgets.erase(iterFind);
+		}
+	}
+
+	void GUIManager::attachWidgetToWindow(const RenderWindow* window, GUIWidget* widget)
+	{
+		auto findIter = mInputMap.find(window);
+
+		if(findIter == mInputMap.end())
+			CM_EXCEPT(InternalErrorException, "Cannot find specified window in the window list.");
+
+		std::vector<GUIWidget*>& widgets = findIter->second;
+
+		bool found = false;
+		for(auto& existingWidget : widgets)
+		{
+			if(existingWidget == widget)
+			{
+				found = true;
+				break;
+			}
+		}
+
+		if(!found)
+			widgets.push_back(widget);
+	}
+
+	void GUIManager::update()
+	{
+
+	}
+
+	void GUIManager::doOnWindowCreated(RenderWindow* window)
+	{
+		mInputMap.insert(std::make_pair(window, std::vector<GUIWidget*>()));
+	}
+
+	void GUIManager::doOnWindowDestroyed(RenderWindow* window)
+	{
+		auto findIter = mInputMap.find(window);
+
+		if(findIter == mInputMap.end())
+			CM_EXCEPT(InternalErrorException, "Cannot find specified window in the window list.");
+
+		mInputMap.erase(findIter);
 	}
 	}
 }
 }

+ 2 - 2
CamelotClient/CamelotClient.cpp

@@ -30,9 +30,9 @@
 #include "CmRTTIType.h"
 #include "CmRTTIType.h"
 #include "CmCursor.h"
 #include "CmCursor.h"
 
 
-//#define DX11
+#define DX11
 //#define DX9
 //#define DX9
-#define GL
+//#define GL
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 using namespace BansheeEditor;
 using namespace BansheeEditor;

+ 4 - 0
CamelotCore/Include/CmRenderTarget.h

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

+ 2 - 0
CamelotCore/Include/CmRenderWindow.h

@@ -175,6 +175,8 @@ namespace CamelotFramework
           */
           */
         void setDeactivateOnFocusChange(bool deactivate);
         void setDeactivateOnFocusChange(bool deactivate);
 
 
+		virtual void destroy();
+
 		static RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow = nullptr);
 		static RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow = nullptr);
 
 
     protected:
     protected:

+ 10 - 0
CamelotCore/Include/CmRenderWindowManager.h

@@ -4,6 +4,8 @@
 #include "CmModule.h"
 #include "CmModule.h"
 #include "CmRenderWindow.h"
 #include "CmRenderWindow.h"
 
 
+#include "boost/signal.hpp"
+
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
 	class CM_EXPORT RenderWindowManager : public Module<RenderWindowManager>
 	class CM_EXPORT RenderWindowManager : public Module<RenderWindowManager>
@@ -13,7 +15,15 @@ namespace CamelotFramework
 		*/
 		*/
 		RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow);
 		RenderWindowPtr create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow);
 
 
+		boost::signal<void(RenderWindow*)> onWindowCreated;
+		boost::signal<void(RenderWindow*)> onWindowDestroyed;
 	protected:
 	protected:
+		friend class RenderWindow;
+
+		std::vector<RenderWindow*> mCreatedWindows;
+
 		virtual RenderWindowPtr createImpl(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow) = 0;
 		virtual RenderWindowPtr createImpl(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow) = 0;
+
+		void windowDestroyed(RenderWindow* window);
 	};
 	};
 }
 }

+ 1 - 0
CamelotCore/Source/CmRenderTarget.cpp

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

+ 8 - 1
CamelotCore/Source/CmRenderWindow.cpp

@@ -41,7 +41,7 @@ namespace CamelotFramework
 
 
 	RenderWindow::~RenderWindow() 
 	RenderWindow::~RenderWindow() 
 	{
 	{
-
+		
 	}
 	}
 
 
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -70,6 +70,13 @@ namespace CamelotFramework
         mAutoDeactivatedOnFocusChange = deactivate;
         mAutoDeactivatedOnFocusChange = deactivate;
     }
     }
 
 
+	void RenderWindow::destroy()
+	{
+		RenderWindowManager::instance().windowDestroyed(this);
+
+		RenderTarget::destroy();
+	}
+
 	RenderWindowPtr RenderWindow::create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow)
 	RenderWindowPtr RenderWindow::create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow)
 	{
 	{
 		return RenderWindowManager::instance().create(desc, parentWindow);
 		return RenderWindowManager::instance().create(desc, parentWindow);

+ 18 - 0
CamelotCore/Source/CmRenderWindowManager.cpp

@@ -8,6 +8,24 @@ namespace CamelotFramework
 		renderWindow->setThisPtr(renderWindow);
 		renderWindow->setThisPtr(renderWindow);
 		renderWindow->initialize();
 		renderWindow->initialize();
 
 
+		mCreatedWindows.push_back(renderWindow.get());
+		
+		if(!onWindowCreated.empty())
+			onWindowCreated(renderWindow.get());
+
 		return renderWindow;
 		return renderWindow;
 	}
 	}
+
+	void RenderWindowManager::windowDestroyed(RenderWindow* window)
+	{
+		auto iterFind = std::find(begin(mCreatedWindows), end(mCreatedWindows), window);
+
+		if(iterFind == mCreatedWindows.end())
+			CM_EXCEPT(InternalErrorException, "Trying to destroy a window that is not in the created windows list.");
+
+		if(!onWindowDestroyed.empty())
+			onWindowDestroyed(window);
+
+		mCreatedWindows.erase(iterFind);
+	}
 }
 }

+ 6 - 0
CamelotCore/Source/CmWindowEventUtilities.cpp

@@ -164,6 +164,9 @@ LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wPa
         if( active )
         if( active )
         {
         {
 		    win->setActive( true );
 		    win->setActive( true );
+
+			if(!win->getHasFocus())
+				win->setHasFocus(true);
         }
         }
         else
         else
         {
         {
@@ -171,6 +174,9 @@ LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wPa
             {
             {
     		    win->setActive( false );
     		    win->setActive( false );
             }
             }
+
+			if(win->getHasFocus())
+				win->setHasFocus(false);
         }
         }
 
 
 	    for( ; start != end; ++start )
 	    for( ; start != end; ++start )

+ 5 - 9
TODO.txt

@@ -24,17 +24,13 @@ GUIWidget::updateMeshes leaks. If I leave the game running I can see memory cont
   - Although more than likely I am loading the model incorrectly since it works in Unity?
   - Although more than likely I am loading the model incorrectly since it works in Unity?
   - I probably want to determine front faces based on normals
   - I probably want to determine front faces based on normals
 
 
+ GUIManager
+  - It starts before RenderWindowManager, which means I can't register the callbacks.
+    - If I start it after I miss main window creation, and also get an assert (not sure why the assert though - didn't explore)
+  - Keep track of window in focus
+
 Immediate TODO:
 Immediate TODO:
- - Issue with rendering same object from multiple cameras:
-   - Material parameters should be copied after being submitted to the render context
-   - Otherwise the last camera that submits the object for rendering ends up being the only one whos view matrix actually gets used.
- - Everything is rendering in both windows
-  - Implement layers for SceneObjects?
-  - Mark EditorWindow GameObjects (containing GUIWidgets and other editor classes) with DontSave and HideInHierarchy flags. User-created elements will exists in the 
-    same hierarchy, they will just not be hidden.
- - Get bounds working correctly
  - (optional) Implement DirectDraw for drawing the bounds so I know they're correct
  - (optional) Implement DirectDraw for drawing the bounds so I know they're correct
- - TextSprite bounds are wrong. Y coordinate is flipped
  - Calculate entire GUIWidget bounds and store them
  - Calculate entire GUIWidget bounds and store them
  - Current way of transforming ORect from GUIWidget is almost certainly not correct
  - Current way of transforming ORect from GUIWidget is almost certainly not correct
  - A way to update mesh buffers without recreating vertex/index buffers (Setting data currently does exactly that)
  - A way to update mesh buffers without recreating vertex/index buffers (Setting data currently does exactly that)