Browse Source

Fixed drag and drop so that mouse capture change event doesn't incorrectly fire before the mouse up event, prematurely stopping the drop action

Marko Pintera 10 years ago
parent
commit
53ff33bd57

+ 3 - 0
BansheeCore/Source/Win32/BsWin32Platform.cpp

@@ -1083,12 +1083,15 @@ namespace BansheeEngine
 				break;
 			}
 		case WM_BS_SETCAPTURE:
+			LOGWRN("SET CAPTURE");
 			SetCapture(hWnd);
 			break;
 		case WM_BS_RELEASECAPTURE:
+			LOGWRN("RELEASE CAPTURE");
 			ReleaseCapture();
 			break;
 		case WM_CAPTURECHANGED:
+			LOGWRN("CAPTURE CHANGED");
 			if(!onMouseCaptureChanged.empty())
 				onMouseCaptureChanged();
 			return 0;

+ 1 - 0
BansheeEngine/Include/BsDragAndDropManager.h

@@ -127,5 +127,6 @@ namespace BansheeEngine
 
 		std::atomic<bool> mCaptureChanged;
 		std::atomic<int> mCaptureActive;
+		std::atomic<unsigned long> mCaptureChangeFrame;
 	};
 }

+ 5 - 1
BansheeEngine/Source/BsDragAndDropManager.cpp

@@ -1,6 +1,7 @@
 #include "BsDragAndDropManager.h"
 #include "BsPlatform.h"
 #include "BsCoreApplication.h"
+#include <BsTime.h>
 
 using namespace std::placeholders;
 
@@ -47,9 +48,11 @@ namespace BansheeEngine
 
 		// This generally happens when window loses focus and capture is lost (e.g. alt+tab)
 		int captureActive = mCaptureActive.load();
-		if(!captureActive && mCaptureChanged.load())
+		if (!captureActive && mCaptureChanged.load() && 
+			(gTime().getFrameNumber() > mCaptureChangeFrame.load())) // Wait one frame to insure input (like mouse up) gets a chance to be processed
 		{
 			endDrag(false);
+			mCaptureChanged.store(false);
 		}
 	}
 
@@ -68,6 +71,7 @@ namespace BansheeEngine
 	{
 		mCaptureActive.fetch_xor(1); // mCaptureActive = !mCaptureActive;
 		mCaptureChanged.store(true);
+		mCaptureChangeFrame.store(gTime().getFrameNumber());
 	}
 
 	void DragAndDropManager::cursorReleased(const PointerEvent& event)

+ 5 - 3
BansheeUtility/Include/BsTime.h

@@ -8,7 +8,7 @@ namespace BansheeEngine
 	/**
 	 * @brief	Manages all time related functionality.
 	 * 			
-	 * @note	Sim thread only 
+	 * @note	Sim thread only unless where specified otherwise.
 	 */
 	class BS_UTILITY_EXPORT Time : public Module<Time>
 	{
@@ -44,8 +44,10 @@ namespace BansheeEngine
 		 * @brief	Returns the number of the current frame. First frame is 0.
 		 *
 		 * @return	The current frame.
+		 *
+		 * @note	Thread safe, but only counts sim thread frames.
 		 */
-		unsigned long getFrameNumber() const { return mCurrentFrame; }
+		unsigned long getFrameNumber() const { return mCurrentFrame.load(); }
 
 		/**
 		 * @brief	Returns the precise time since application start, in microseconds.
@@ -84,7 +86,7 @@ namespace BansheeEngine
 
 		UINT64 mAppStartTime; /**< Time the application started, in microseconds */
 		unsigned long mLastFrameTime; /**< Time since last runOneFrame call, In microseconds */
-		unsigned long mCurrentFrame;
+		std::atomic<unsigned long> mCurrentFrame;
 
 		Timer* mTimer;
 	};

+ 2 - 2
BansheeUtility/Source/BsTime.cpp

@@ -6,7 +6,7 @@ namespace BansheeEngine
 	const double Time::MICROSEC_TO_SEC = 1.0/1000000.0;
 
 	Time::Time()
-		:mAppStartTime(0), mLastFrameTime(0), mFrameDelta(0.0f), mTimeSinceStart(0.0f), mCurrentFrame(0)
+		:mAppStartTime(0), mLastFrameTime(0), mFrameDelta(0.0f), mTimeSinceStart(0.0f), mCurrentFrame(0UL)
 	{
 		mTimer = bs_new<Timer>();
 		mAppStartTime = (UINT64)mTimer->getStartMs();
@@ -28,7 +28,7 @@ namespace BansheeEngine
 
 		mLastFrameTime = currentFrameTime;
 
-		mCurrentFrame++;
+		mCurrentFrame.fetch_add(1, std::memory_order_relaxed);
 	}
 
 	UINT64 Time::getTimePrecise() const

+ 0 - 3
TODO.txt

@@ -26,9 +26,6 @@ return them in checkForModifications?
 Project window
 
 Dropping doesn't work. endDrag in DragAndDropManager gets called before cursorReleased()
-Destroying Renderable objects doesn't seem to properly clear them from the renderer
-Add mesh scale to FBX importer (and default it to 0.01 or whatever makes the dragon look normal sized)
-There's still an issue with dragging a selection area in the scroll box
 
 Later:
  - Hook up ping effect so it triggers when I select a resource or sceneobject