Procházet zdrojové kódy

Better handling of drag events and added EndDrag event

Marko Pintera před 12 roky
rodič
revize
8247cbaf25

+ 5 - 2
BansheeEngine/Include/BsGUIManager.h

@@ -38,11 +38,14 @@ namespace BansheeEngine
 		CM::vector<GUIWidget*>::type mWidgets;
 		CM::vector<GUIWidget*>::type mWidgets;
 		CM::unordered_map<const CM::Viewport*, GUIRenderData>::type mCachedGUIData;
 		CM::unordered_map<const CM::Viewport*, GUIRenderData>::type mCachedGUIData;
 
 
+		// Element and widget mouse is currently over
 		GUIWidget* mMouseOverWidget;
 		GUIWidget* mMouseOverWidget;
 		GUIElement* mMouseOverElement;
 		GUIElement* mMouseOverElement;
 
 
-		GUIWidget* mDraggedWidget;
-		GUIElement* mDraggedElement;
+		// Element and widget that's being clicked on
+		GUIWidget* mActiveWidget;
+		GUIElement* mActiveElement;
+		CM::UINT32 mActiveMouseButton;
 
 
 		bool mSeparateMeshesByWidget;
 		bool mSeparateMeshesByWidget;
 		bool mLastFrameButtonState[CM::MB_Count];
 		bool mLastFrameButtonState[CM::MB_Count];

+ 2 - 1
BansheeEngine/Include/BsGUIMouseEvent.h

@@ -13,7 +13,8 @@ namespace BansheeEngine
 		MouseDown,
 		MouseDown,
 		MouseUp,
 		MouseUp,
 		MouseMove,
 		MouseMove,
-		MouseDrag
+		MouseDrag,
+		MouseDragEnd
 	};
 	};
 
 
 	class BS_EXPORT GUIMouseEvent
 	class BS_EXPORT GUIMouseEvent

+ 2 - 1
BansheeEngine/Source/BsGUIArea.cpp

@@ -8,7 +8,8 @@ using namespace CamelotFramework;
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	GUIArea::GUIArea(GUIWidget& widget, UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT16 depth)
 	GUIArea::GUIArea(GUIWidget& widget, UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT16 depth)
-		:mWidget(widget), mX(x), mY(y), mWidth(width), mHeight(height), mDepth(depth), mIsDirty(true)
+		:mWidget(widget), mX(x), mY(y), mWidth(width), mHeight(height), mDepth(depth), mIsDirty(true), 
+		mResizeHeightWithWindow(false), mResizeWidthWithWindow(false)
 	{
 	{
 		mLayout = cm_new<GUILayoutX, PoolAlloc>();
 		mLayout = cm_new<GUILayoutX, PoolAlloc>();
 
 

+ 49 - 22
BansheeEngine/Source/BsGUIManager.cpp

@@ -42,7 +42,8 @@ namespace BansheeEngine
 	};
 	};
 
 
 	GUIManager::GUIManager()
 	GUIManager::GUIManager()
-		:mMouseOverElement(nullptr), mMouseOverWidget(nullptr), mSeparateMeshesByWidget(true), mDraggedElement(nullptr), mDraggedWidget(nullptr)
+		:mMouseOverElement(nullptr), mMouseOverWidget(nullptr), mSeparateMeshesByWidget(true), mActiveElement(nullptr), 
+		mActiveWidget(nullptr), mActiveMouseButton(0)
 	{
 	{
 		for(int i = 0; i < MB_Count; i++)
 		for(int i = 0; i < MB_Count; i++)
 			mLastFrameButtonState[i] = false;
 			mLastFrameButtonState[i] = false;
@@ -471,12 +472,14 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
+		// 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)
 		if(topMostElement != mMouseOverElement)
 		{
 		{
 			if(mMouseOverElement != nullptr)
 			if(mMouseOverElement != nullptr)
 			{
 			{
 				// Send MouseOut event
 				// Send MouseOut event
-				if(mDraggedElement == nullptr || mMouseOverElement == mDraggedElement)
+				if(mActiveElement == nullptr || mMouseOverElement == mActiveElement)
 				{
 				{
 					Int2 curLocalPos = getWidgetRelativeCursorPos(*mMouseOverWidget);
 					Int2 curLocalPos = getWidgetRelativeCursorPos(*mMouseOverWidget);
 
 
@@ -488,7 +491,7 @@ namespace BansheeEngine
 			if(topMostElement != nullptr)
 			if(topMostElement != nullptr)
 			{
 			{
 				// Send MouseOver event
 				// Send MouseOver event
-				if(mDraggedElement == nullptr || topMostElement == mDraggedElement)
+				if(mActiveElement == nullptr || topMostElement == mActiveElement)
 				{
 				{
 					GUIMouseEvent event(GUIMouseEventType::MouseOver, localPos);
 					GUIMouseEvent event(GUIMouseEventType::MouseOver, localPos);
 					widgetInFocus->_mouseEvent(topMostElement, event);
 					widgetInFocus->_mouseEvent(topMostElement, event);
@@ -496,25 +499,25 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
-		if(mDraggedElement != nullptr)
+		// If mouse is being held down send MouseDrag events
+		if(mActiveElement != nullptr)
 		{
 		{
-			Int2 curLocalPos = getWidgetRelativeCursorPos(*mDraggedWidget);
+			Int2 curLocalPos = getWidgetRelativeCursorPos(*mActiveWidget);
 
 
 			if(mLastCursorLocalPos != curLocalPos)
 			if(mLastCursorLocalPos != curLocalPos)
 			{
 			{
 				GUIMouseEvent event(GUIMouseEventType::MouseDrag, curLocalPos);
 				GUIMouseEvent event(GUIMouseEventType::MouseDrag, curLocalPos);
 				event._setDragAmount(curLocalPos - mLastCursorLocalPos);
 				event._setDragAmount(curLocalPos - mLastCursorLocalPos);
-				mDraggedWidget->_mouseEvent(mDraggedElement, event);
+				mActiveWidget->_mouseEvent(mActiveElement, event);
 
 
 				mLastCursorLocalPos = curLocalPos;
 				mLastCursorLocalPos = curLocalPos;
 			}
 			}
 		}
 		}
-
-		if(topMostElement != nullptr)
+		else // Otherwise, send MouseMove events if we are hovering over any element
 		{
 		{
-			// Send MouseMove event
-			if(mDraggedElement == nullptr)
+			if(topMostElement != nullptr)
 			{
 			{
+				// Send MouseMove event
 				if(mLastCursorLocalPos != localPos)
 				if(mLastCursorLocalPos != localPos)
 				{
 				{
 					GUIMouseEvent event(GUIMouseEventType::MouseMove, localPos);
 					GUIMouseEvent event(GUIMouseEventType::MouseMove, localPos);
@@ -523,32 +526,56 @@ namespace BansheeEngine
 					mLastCursorLocalPos = localPos;
 					mLastCursorLocalPos = localPos;
 				}
 				}
 			}
 			}
+		}
 
 
-			// Send MouseDown and MouseUp events
-			for(int i = 0; i < MB_Count; i++)
+		// Check for MouseDown and MouseUp events.
+		for(int i = 0; i < MB_Count; i++)
+		{
+			bool buttonDown = gInput().isButtonDown((MouseButton)i);
+			if(mLastFrameButtonState[i] != buttonDown)
 			{
 			{
-				bool buttonDown = gInput().isButtonDown((MouseButton)i);
-				if(mLastFrameButtonState[i] != buttonDown)
+				// Mouse button is being pressed
+				if(buttonDown)
 				{
 				{
-					if(buttonDown)
+					// We only check for mouse down if mouse isn't already being held down, and we are hovering over an element
+					bool acceptMouseDown = mActiveElement == nullptr && topMostElement != nullptr;
+					if(acceptMouseDown)
 					{
 					{
 						GUIMouseEvent event(GUIMouseEventType::MouseDown, localPos, (MouseButton)i);
 						GUIMouseEvent event(GUIMouseEventType::MouseDown, localPos, (MouseButton)i);
 						widgetInFocus->_mouseEvent(topMostElement, event);
 						widgetInFocus->_mouseEvent(topMostElement, event);
 
 
-						mDraggedElement = topMostElement;
-						mDraggedWidget = widgetInFocus;
+						mActiveElement = topMostElement;
+						mActiveWidget = widgetInFocus;
+						mActiveMouseButton = i;
+
+						mLastFrameButtonState[i] = buttonDown;
 					}
 					}
-					else
+				}
+				else
+				{
+					// Send MouseUp event only if we are over the active element (we don't want to accidentally trigger other elements).
+					// And only activate when a button that originally caused the active state is released, otherwise ignore it.
+					bool acceptMouseUp = mActiveMouseButton == i && (topMostElement != nullptr && mActiveElement == topMostElement);
+					if(acceptMouseUp)
 					{
 					{
 						GUIMouseEvent event(GUIMouseEventType::MouseUp, localPos, (MouseButton)i);
 						GUIMouseEvent event(GUIMouseEventType::MouseUp, localPos, (MouseButton)i);
 						widgetInFocus->_mouseEvent(topMostElement, event);
 						widgetInFocus->_mouseEvent(topMostElement, event);
-
-						mDraggedElement = nullptr;
-						mDraggedWidget = nullptr;
 					}
 					}
 
 
-					mLastFrameButtonState[i] = buttonDown;
+					// 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);
+
+						mActiveElement = nullptr;
+						mActiveWidget = nullptr;
+						mActiveMouseButton = 0;
+					}	
 				}
 				}
+
+				mLastFrameButtonState[i] = buttonDown;
 			}
 			}
 		}
 		}
 
 

+ 1 - 1
BansheeEngine/Source/BsGUIWindowFrame.cpp

@@ -268,7 +268,7 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
-		if(ev.getType() == GUIMouseEventType::MouseOut)
+		if(ev.getType() == GUIMouseEventType::MouseOut || ev.getType() == GUIMouseEventType::MouseDragEnd)
 		{
 		{
 			if(mResizeCursorSet)
 			if(mResizeCursorSet)
 			{
 			{