Prechádzať zdrojové kódy

Revamped mouse events and added more information to the event structure

Marko Pintera 12 rokov pred
rodič
commit
314ec83cd3

+ 1 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -199,6 +199,7 @@
     <ClCompile Include="Source\BsGUILayoutY.cpp" />
     <ClCompile Include="Source\BsGUIManager.cpp" />
     <ClCompile Include="Source\BsGUIMaterialManager.cpp" />
+    <ClCompile Include="Source\BsGUIMouseEvent.cpp" />
     <ClCompile Include="Source\BsGUISkin.cpp" />
     <ClCompile Include="Source\BsGUITexture.cpp" />
     <ClCompile Include="Source\BsGUIToggle.cpp" />

+ 3 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -251,5 +251,8 @@
     <ClCompile Include="Source\BsGUIInputBox.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIMouseEvent.cpp">
+      <Filter>Source Files\GUI</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 0
BansheeEngine/Include/BsGUIInputBox.h

@@ -50,6 +50,8 @@ namespace BansheeEngine
 		ImageSprite* mImageSprite;
 		TextSprite* mTextSprite;
 		CM::UINT32 mNumImageRenderElements;
+		bool mInputCursorSet;
+		bool mDragInProgress;
 
 		IMAGE_SPRITE_DESC mImageDesc;
 		CM::String mText;

+ 3 - 0
BansheeEngine/Include/BsGUIManager.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "BsPrerequisites.h"
+#include "BsGUIMouseEvent.h"
 #include "CmModule.h"
 #include "CmInputHandler.h"
 #include "CmDeferredRenderContextFwd.h"
@@ -51,6 +52,8 @@ namespace BansheeEngine
 		bool mLastFrameButtonState[CM::MB_Count];
 		CM::Int2 mLastCursorLocalPos;
 
+		GUIMouseEvent mMouseEvent;
+
 		void updateMeshes();
 		void updateInput();
 

+ 16 - 4
BansheeEngine/Include/BsGUIMouseEvent.h

@@ -14,26 +14,38 @@ namespace BansheeEngine
 		MouseUp,
 		MouseMove,
 		MouseDrag,
+		MouseDragStart,
 		MouseDragEnd
 	};
 
 	class BS_EXPORT GUIMouseEvent
 	{
 	public:
-		GUIMouseEvent(GUIMouseEventType type, const CM::Int2& position, CM::MouseButton button = CM::MB_Left)
-			:mType(type), mPosition(position), mButton(button)
-		{ }
+		GUIMouseEvent();
+		GUIMouseEvent(bool buttonStates[CM::MB_Count]);
 
 		const CM::Int2& getPosition() const { return mPosition; }
 		GUIMouseEventType getType() const { return mType; }
 		CM::MouseButton getButton() const { return mButton; }
 		CM::Int2 getDragAmount() const { return mDragAmount; }
+		bool isButtonDown(CM::MouseButton button) const { return mButtonStates[(int)button]; }
+		GUIElement* getMouseOverElement() const { return mMouseOverElement; }
 
-		void _setDragAmount(CM::Int2 dragAmount) { mDragAmount = dragAmount; }
+		void _setMouseOverData(GUIElement* mouseOverElement, const CM::Int2& position);
+		void _setMouseOutData(GUIElement* mouseOverElement, const CM::Int2& position);
+		void _setMouseMoveData(GUIElement* mouseOverElement, const CM::Int2& position);
+		void _setMouseUpData(GUIElement* mouseOverElement, const CM::Int2& position, CM::MouseButton button);
+		void _setMouseDownData(GUIElement* mouseOverElement, const CM::Int2& position, CM::MouseButton button);
+
+		void _setMouseDragData(GUIElement* mouseOverElement, const CM::Int2& position, const CM::Int2& dragAmount);
+		void _setMouseDragStartData(GUIElement* mouseOverElement, const CM::Int2& position);
+		void _setMouseDragEndData(GUIElement* mouseOverElement, const CM::Int2& position);
 	private:
 		CM::Int2 mPosition;
 		CM::Int2 mDragAmount;
 		GUIMouseEventType mType;
 		CM::MouseButton mButton;
+		bool mButtonStates[CM::MB_Count];
+		GUIElement* mMouseOverElement;
 	};
 }

+ 32 - 1
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -7,6 +7,7 @@
 #include "BsGUILayoutOptions.h"
 #include "BsGUIMouseEvent.h"
 #include "CmTexture.h"
+#include "CmCursor.h"
 
 using namespace CamelotFramework;
 
@@ -19,7 +20,7 @@ namespace BansheeEngine
 	}
 
 	GUIInputBox::GUIInputBox(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
-		:GUIElement(parent, style, layoutOptions), mNumImageRenderElements(0)
+		:GUIElement(parent, style, layoutOptions), mNumImageRenderElements(0), mInputCursorSet(false), mDragInProgress(false)
 	{
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 		mTextSprite = cm_new<TextSprite, PoolAlloc>();
@@ -172,6 +173,12 @@ namespace BansheeEngine
 			mImageDesc.texture = mStyle->hover.texture;
 			markAsDirty();
 
+			if(!mInputCursorSet)
+			{
+				Cursor::setCursor(CursorType::IBeam);
+				mInputCursorSet = true;
+			}
+
 			return true;
 		}
 		else if(ev.getType() == GUIMouseEventType::MouseOut)
@@ -179,6 +186,12 @@ namespace BansheeEngine
 			mImageDesc.texture = mStyle->normal.texture;
 			markAsDirty();
 
+			if(!mDragInProgress && mInputCursorSet)
+			{
+				Cursor::setCursor(CursorType::Arrow);
+				mInputCursorSet = false;
+			}
+
 			return true;
 		}
 		else if(ev.getType() == GUIMouseEventType::MouseDown)
@@ -195,6 +208,24 @@ namespace BansheeEngine
 
 			return true;
 		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragStart)
+		{
+			mDragInProgress = true;
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragEnd)
+		{
+			mDragInProgress = false;
+
+			if(ev.getMouseOverElement() != this && mInputCursorSet)
+			{
+				Cursor::setCursor(CursorType::Arrow);
+				mInputCursorSet = false;
+			}
+
+			return true;
+		}
 
 		return false;
 	}

+ 30 - 17
BansheeEngine/Source/BsGUIManager.cpp

@@ -1,7 +1,6 @@
 #include "BsGUIManager.h"
 #include "BsGUIWidget.h"
 #include "BsGUIElement.h"
-#include "BsGUIMouseEvent.h"
 #include "CmSceneObject.h"
 #include "CmMaterial.h"
 #include "CmMeshData.h"
@@ -472,6 +471,16 @@ namespace BansheeEngine
 			}
 		}
 
+		/************************************************************************/
+		/* 								MOUSE EVENTS                      		*/
+		/************************************************************************/
+
+		bool buttonStates[(int)MB_Count];
+		for(int i = 0; i < MB_Count; i++)
+			buttonStates[i] = gInput().isButtonDown((MouseButton)i);
+
+		mMouseEvent = GUIMouseEvent(buttonStates);
+
 		// Send MouseOver/MouseOut events to any elements the mouse passes over, except when
 		// mouse is being held down, in which we only send them to the active element
 		if(topMostElement != mMouseOverElement)
@@ -483,8 +492,8 @@ namespace BansheeEngine
 				{
 					Int2 curLocalPos = getWidgetRelativeCursorPos(*mMouseOverWidget);
 
-					GUIMouseEvent event(GUIMouseEventType::MouseOut, curLocalPos);
-					mMouseOverWidget->_mouseEvent(mMouseOverElement, event);
+					mMouseEvent._setMouseOutData(topMostElement, curLocalPos);
+					mMouseOverWidget->_mouseEvent(mMouseOverElement, mMouseEvent);
 				}
 			}
 
@@ -493,8 +502,8 @@ namespace BansheeEngine
 				// Send MouseOver event
 				if(mActiveElement == nullptr || topMostElement == mActiveElement)
 				{
-					GUIMouseEvent event(GUIMouseEventType::MouseOver, localPos);
-					widgetInFocus->_mouseEvent(topMostElement, event);
+					mMouseEvent._setMouseOverData(topMostElement, localPos);
+					widgetInFocus->_mouseEvent(topMostElement, mMouseEvent);
 				}
 			}
 		}
@@ -506,9 +515,8 @@ namespace BansheeEngine
 
 			if(mLastCursorLocalPos != curLocalPos)
 			{
-				GUIMouseEvent event(GUIMouseEventType::MouseDrag, curLocalPos);
-				event._setDragAmount(curLocalPos - mLastCursorLocalPos);
-				mActiveWidget->_mouseEvent(mActiveElement, event);
+				mMouseEvent._setMouseDragData(topMostElement, curLocalPos, curLocalPos - mLastCursorLocalPos);
+				mActiveWidget->_mouseEvent(mActiveElement, mMouseEvent);
 
 				mLastCursorLocalPos = curLocalPos;
 			}
@@ -520,8 +528,8 @@ namespace BansheeEngine
 				// Send MouseMove event
 				if(mLastCursorLocalPos != localPos)
 				{
-					GUIMouseEvent event(GUIMouseEventType::MouseMove, localPos);
-					widgetInFocus->_mouseEvent(topMostElement, event);
+					mMouseEvent._setMouseMoveData(topMostElement, localPos);
+					widgetInFocus->_mouseEvent(topMostElement, mMouseEvent);
 
 					mLastCursorLocalPos = localPos;
 				}
@@ -531,7 +539,7 @@ namespace BansheeEngine
 		// Check for MouseDown and MouseUp events.
 		for(int i = 0; i < MB_Count; i++)
 		{
-			bool buttonDown = gInput().isButtonDown((MouseButton)i);
+			bool buttonDown = buttonStates[i];
 			if(mLastFrameButtonState[i] != buttonDown)
 			{
 				// Mouse button is being pressed
@@ -541,8 +549,13 @@ namespace BansheeEngine
 					bool acceptMouseDown = mActiveElement == nullptr && topMostElement != nullptr;
 					if(acceptMouseDown)
 					{
-						GUIMouseEvent event(GUIMouseEventType::MouseDown, localPos, (MouseButton)i);
-						widgetInFocus->_mouseEvent(topMostElement, event);
+						mMouseEvent._setMouseDownData(topMostElement, localPos, (MouseButton)i);
+						widgetInFocus->_mouseEvent(topMostElement, mMouseEvent);
+
+						// DragStart is for all intents and purposes same as mouse down but since I need a DragEnd event, I feel a separate DragStart
+						// event was also needed to make things clearer.
+						mMouseEvent._setMouseDragStartData(topMostElement, localPos);
+						widgetInFocus->_mouseEvent(topMostElement, mMouseEvent);
 
 						mActiveElement = topMostElement;
 						mActiveWidget = widgetInFocus;
@@ -558,16 +571,16 @@ namespace BansheeEngine
 					bool acceptMouseUp = mActiveMouseButton == i && (topMostElement != nullptr && mActiveElement == topMostElement);
 					if(acceptMouseUp)
 					{
-						GUIMouseEvent event(GUIMouseEventType::MouseUp, localPos, (MouseButton)i);
-						widgetInFocus->_mouseEvent(topMostElement, event);
+						mMouseEvent._setMouseUpData(topMostElement, localPos, (MouseButton)i);
+						widgetInFocus->_mouseEvent(topMostElement, mMouseEvent);
 					}
 
 					// Send DragEnd event to whichever element is active
 					bool acceptEndDrag = mActiveMouseButton == i && mActiveElement != nullptr;
 					if(acceptEndDrag)
 					{
-						GUIMouseEvent event(GUIMouseEventType::MouseDragEnd, localPos, (MouseButton)i);
-						mActiveWidget->_mouseEvent(mActiveElement, event);
+						mMouseEvent._setMouseDragEndData(topMostElement, localPos);
+						mActiveWidget->_mouseEvent(mActiveElement, mMouseEvent);
 
 						mActiveElement = nullptr;
 						mActiveWidget = nullptr;

+ 90 - 0
BansheeEngine/Source/BsGUIMouseEvent.cpp

@@ -0,0 +1,90 @@
+#include "BsGUIMouseEvent.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	GUIMouseEvent::GUIMouseEvent()
+		:mType(GUIMouseEventType::MouseMove), mButton(MB_Left), mMouseOverElement(nullptr)
+	{
+		memset(mButtonStates, 0, sizeof(mButtonStates));
+	}
+
+	GUIMouseEvent::GUIMouseEvent(bool buttonStates[MB_Count])
+		:mType(GUIMouseEventType::MouseMove), mButton(MB_Left), mMouseOverElement(nullptr)
+	{
+		memcpy(mButtonStates, buttonStates, sizeof(mButtonStates));
+	}
+
+	void GUIMouseEvent::_setMouseOverData(GUIElement* mouseOverElement, const Int2& position)
+	{
+		mType = GUIMouseEventType::MouseOver;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseOutData(GUIElement* mouseOverElement, const Int2& position)
+	{
+		mType = GUIMouseEventType::MouseOut;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseMoveData(GUIElement* mouseOverElement, const Int2& position)
+	{
+		mType = GUIMouseEventType::MouseMove;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseUpData(GUIElement* mouseOverElement, const Int2& position, MouseButton button)
+	{
+		mType = GUIMouseEventType::MouseUp;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = button;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseDownData(GUIElement* mouseOverElement, const Int2& position, MouseButton button)
+	{
+		mType = GUIMouseEventType::MouseDown;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = button;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseDragData(GUIElement* mouseOverElement, const Int2& position, const Int2& dragAmount)
+	{
+		mType = GUIMouseEventType::MouseDrag;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = dragAmount;
+	}
+
+	void GUIMouseEvent::_setMouseDragStartData(GUIElement* mouseOverElement, const Int2& position)
+	{
+		mType = GUIMouseEventType::MouseDragStart;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = Int2();
+	}
+
+	void GUIMouseEvent::_setMouseDragEndData(GUIElement* mouseOverElement, const Int2& position)
+	{
+		mType = GUIMouseEventType::MouseDragEnd;
+		mPosition = position;
+		mMouseOverElement = mouseOverElement;
+		mButton = MB_Left;
+		mDragAmount = Int2();
+	}
+}