Pārlūkot izejas kodu

Added panning gesture, activated by mouse wheel press

Ivan Savenko 2 gadi atpakaļ
vecāks
revīzija
48859e186e

+ 4 - 0
client/eventsSDL/InputHandler.cpp

@@ -168,7 +168,11 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 			// This prevents freezes when every motion event takes longer to handle than interval at which
 			// the events arrive (like dragging on the minimap in world view, with redraw at every event)
 			// so that the events would start piling up faster than they can be processed.
+			int xAccumulated = eventsQueue.back().motion.xrel + ev.motion.xrel;
+			int yAccumulated = eventsQueue.back().motion.yrel + ev.motion.yrel;
 			eventsQueue.back() = ev;
+			eventsQueue.back().motion.xrel = xAccumulated;
+			eventsQueue.back().motion.yrel = yAccumulated;
 			return;
 		}
 		eventsQueue.push_back(ev);

+ 4 - 6
client/eventsSDL/InputSourceMouse.cpp

@@ -22,9 +22,13 @@
 void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
 {
 	Point newPosition(motion.x, motion.y);
+	Point distance(-motion.xrel, -motion.yrel);
 
 	GH.input().setCursorPosition(newPosition);
 
+	if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE))
+		GH.events().dispatchGesturePanning(distance);
+
 	mouseButtonsMask = motion.state;
 
 }
@@ -44,9 +48,6 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b
 		case SDL_BUTTON_RIGHT:
 			GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
 			break;
-		case SDL_BUTTON_MIDDLE:
-			GH.events().dispatchMouseButtonPressed(MouseButton::MIDDLE, position);
-			break;
 	}
 }
 
@@ -71,9 +72,6 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
 		case SDL_BUTTON_RIGHT:
 			GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
 			break;
-		case SDL_BUTTON_MIDDLE:
-			GH.events().dispatchMouseButtonReleased(MouseButton::MIDDLE, position);
-			break;
 	}
 }
 

+ 2 - 9
client/eventsSDL/InputSourceTouch.cpp

@@ -104,11 +104,6 @@ void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinge
 			break;
 		}
 		case TouchState::TAP_DOWN_SHORT:
-		{
-			GH.input().setCursorPosition(convertTouchToMouse(tfinger));
-			state = TouchState::TAP_DOWN_DOUBLE;
-			break;
-		}
 		case TouchState::TAP_DOWN_PANNING:
 		{
 			GH.input().setCursorPosition(convertTouchToMouse(tfinger));
@@ -116,10 +111,6 @@ void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinge
 			break;
 		}
 		case TouchState::TAP_DOWN_DOUBLE:
-		{
-			// TODO? ignore?
-			break;
-		}
 		case TouchState::TAP_DOWN_LONG:
 		{
 			// no-op
@@ -163,6 +154,8 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
 		{
 			if (SDL_GetNumTouchFingers(tfinger.touchId) == 1)
 				state = TouchState::TAP_DOWN_PANNING;
+			if (SDL_GetNumTouchFingers(tfinger.touchId) == 0)
+				state = TouchState::IDLE;
 			break;
 		}
 		case TouchState::TAP_DOWN_LONG:

+ 21 - 6
client/gui/EventDispatcher.cpp

@@ -28,7 +28,6 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb)
 
 	processList(AEventsReceiver::LCLICK, lclickable);
 	processList(AEventsReceiver::RCLICK, rclickable);
-	processList(AEventsReceiver::MCLICK, mclickable);
 	processList(AEventsReceiver::HOVER, hoverable);
 	processList(AEventsReceiver::MOVE, motioninterested);
 	processList(AEventsReceiver::KEYBOARD, keyinterested);
@@ -36,6 +35,7 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb)
 	processList(AEventsReceiver::WHEEL, wheelInterested);
 	processList(AEventsReceiver::DOUBLECLICK, doubleClickInterested);
 	processList(AEventsReceiver::TEXTINPUT, textInterested);
+	processList(AEventsReceiver::GESTURE_PANNING, panningInterested);
 }
 
 void EventDispatcher::activateElement(AEventsReceiver * elem, ui16 activityFlag)
@@ -120,8 +120,6 @@ EventDispatcher::EventReceiversList & EventDispatcher::getListForMouseButton(Mou
 			return lclickable;
 		case MouseButton::RIGHT:
 			return rclickable;
-		case MouseButton::MIDDLE:
-			return mclickable;
 	}
 	throw std::runtime_error("Invalid mouse button in getListForMouseButton");
 }
@@ -138,7 +136,7 @@ void EventDispatcher::dispatchMouseDoubleClick(const Point & position)
 
 		if(i->isInside(position))
 		{
-			i->onDoubleClick();
+			i->clickDouble();
 			doubleClicked = true;
 		}
 	}
@@ -172,10 +170,19 @@ void EventDispatcher::handleMouseButtonClick(EventReceiversList & interestedObjs
 		{
 			if(isPressed)
 				i->currentMouseState[btn] = isPressed;
-			i->click(btn, isPressed, prev);
+
+			if (btn == MouseButton::LEFT)
+				i->clickLeft(isPressed, prev);
+			if (btn == MouseButton::RIGHT)
+				i->clickRight(isPressed, prev);
 		}
 		else if(!isPressed)
-			i->click(btn, boost::logic::indeterminate, prev);
+		{
+			if (btn == MouseButton::LEFT)
+				i->clickLeft(boost::logic::indeterminate, prev);
+			if (btn == MouseButton::RIGHT)
+				i->clickRight(boost::logic::indeterminate, prev);
+		}
 	}
 }
 
@@ -206,6 +213,14 @@ void EventDispatcher::dispatchTextEditing(const std::string & text)
 	}
 }
 
+void EventDispatcher::dispatchGesturePanning(const Point & distance)
+{
+	for(auto it : panningInterested)
+	{
+		it->gesturePanning(distance);
+	}
+}
+
 void EventDispatcher::dispatchMouseMoved(const Point & position)
 {
 	EventReceiversList newlyHovered;

+ 4 - 2
client/gui/EventDispatcher.h

@@ -25,7 +25,6 @@ class EventDispatcher
 	/// list of UI elements that are interested in particular event
 	EventReceiversList lclickable;
 	EventReceiversList rclickable;
-	EventReceiversList mclickable;
 	EventReceiversList hoverable;
 	EventReceiversList keyinterested;
 	EventReceiversList motioninterested;
@@ -33,6 +32,7 @@ class EventDispatcher
 	EventReceiversList wheelInterested;
 	EventReceiversList doubleClickInterested;
 	EventReceiversList textInterested;
+	EventReceiversList panningInterested;
 
 	EventReceiversList & getListForMouseButton(MouseButton button);
 
@@ -60,7 +60,9 @@ public:
 	void dispatchMouseButtonReleased(const MouseButton & button, const Point & position);
 	void dispatchMouseScrolled(const Point & distance, const Point & position);
 	void dispatchMouseDoubleClick(const Point & position);
-	void dispatchMouseMoved(const Point & position);
+	void dispatchMouseMoved(const Point & distance);
+
+	void dispatchGesturePanning(const Point & position);
 
 	/// Text input events
 	void dispatchTextInput(const std::string & text);

+ 0 - 17
client/gui/EventsReceiver.cpp

@@ -55,20 +55,3 @@ void AEventsReceiver::deactivateEvents(ui16 what)
 		activeState &= ~GENERAL;
 	GH.events().deactivateElement(this, what & activeState);
 }
-
-void AEventsReceiver::click(MouseButton btn, tribool down, bool previousState)
-{
-	switch(btn)
-	{
-	default:
-	case MouseButton::LEFT:
-		clickLeft(down, previousState);
-		break;
-	case MouseButton::MIDDLE:
-		clickMiddle(down, previousState);
-		break;
-	case MouseButton::RIGHT:
-		clickRight(down, previousState);
-		break;
-	}
-}

+ 8 - 8
client/gui/EventsReceiver.h

@@ -29,7 +29,6 @@ class AEventsReceiver
 	bool strongInterestState;
 	std::map<MouseButton, bool> currentMouseState;
 
-	void click(MouseButton btn, tribool down, bool previousState);
 protected:
 
 	/// If set, UI element will receive all mouse movement events, even those outside this element
@@ -42,20 +41,21 @@ protected:
 
 	virtual void clickLeft(tribool down, bool previousState) {}
 	virtual void clickRight(tribool down, bool previousState) {}
-	virtual void clickMiddle(tribool down, bool previousState) {}
+	virtual void clickDouble() {}
 
-	virtual void textInputed(const std::string & enteredText) {}
-	virtual void textEdited(const std::string & enteredText) {}
-
-	virtual void tick(uint32_t msPassed) {}
+	virtual void gesturePanning(const Point & distanceDelta) {}
 	virtual void wheelScrolled(bool down, bool in) {}
 	virtual void mouseMoved(const Point & cursorPosition) {}
 	virtual void hover(bool on) {}
-	virtual void onDoubleClick() {}
+
+	virtual void textInputed(const std::string & enteredText) {}
+	virtual void textEdited(const std::string & enteredText) {}
 
 	virtual void keyPressed(EShortcut key) {}
 	virtual void keyReleased(EShortcut key) {}
 
+	virtual void tick(uint32_t msPassed) {}
+
 	virtual bool captureThisKey(EShortcut key) = 0;
 	virtual bool isInside(const Point & position) = 0;
 
@@ -64,7 +64,7 @@ public:
 	virtual ~AEventsReceiver() = default;
 
 	/// These are the arguments that can be used to determine what kind of input UI element will receive
-	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, MCLICK=1024, ALL=0xffff};
+	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, GESTURE_PANNING=1024, ALL=0xffff};
 
 	/// Returns true if element is currently hovered by mouse
 	bool isHovered() const;

+ 1 - 1
client/lobby/SelectionTab.cpp

@@ -313,7 +313,7 @@ void SelectionTab::keyPressed(EShortcut key)
 	select((int)selectionPos - slider->getValue() + moveBy);
 }
 
-void SelectionTab::onDoubleClick()
+void SelectionTab::clickDouble()
 {
 	if(getLine() != -1) //double clicked scenarios list
 	{

+ 1 - 1
client/lobby/SelectionTab.h

@@ -68,7 +68,7 @@ public:
 	void clickLeft(tribool down, bool previousState) override;
 	void keyPressed(EShortcut key) override;
 
-	void onDoubleClick() override;
+	void clickDouble() override;
 
 	void filter(int size, bool selectFirst = false); //0 - all
 	void sortBy(int criteria);

+ 1 - 1
client/mapView/MapView.cpp

@@ -117,7 +117,7 @@ void MapView::onMapScrolled(const Point & distance)
 void MapView::onMapSwiped(const Point & viewPosition)
 {
 	isSwiping = true;
-	controller->setViewCenter(viewPosition, model->getLevel());
+	controller->setViewCenter(model->getMapViewCenter() + viewPosition, model->getLevel());
 }
 
 void MapView::onMapSwipeEnded()

+ 5 - 74
client/mapView/MapViewActions.cpp

@@ -25,21 +25,11 @@
 MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel> & model)
 	: model(model)
 	, owner(owner)
-	, isSwiping(false)
 {
 	pos.w = model->getPixelsVisibleDimensions().x;
 	pos.h = model->getPixelsVisibleDimensions().y;
 
-	addUsedEvents(LCLICK | RCLICK | MCLICK | HOVER | MOVE | WHEEL);
-}
-
-bool MapViewActions::swipeEnabled() const
-{
-#if defined(VCMI_ANDROID) || defined(VCMI_IOS)
-	return settings["general"]["swipe"].Bool();
-#else
-	return settings["general"]["swipeDesktop"].Bool();
-#endif
+	addUsedEvents(LCLICK | RCLICK | GESTURE_PANNING | HOVER | MOVE | WHEEL);
 }
 
 void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
@@ -52,18 +42,8 @@ void MapViewActions::clickLeft(tribool down, bool previousState)
 	if(indeterminate(down))
 		return;
 
-	if(swipeEnabled())
-	{
-		if(handleSwipeStateChange(static_cast<bool>(down)))
-		{
-			return; // if swipe is enabled, we don't process "down" events and wait for "up" (to make sure this wasn't a swiping gesture)
-		}
-	}
-	else
-	{
-		if(down == false)
-			return;
-	}
+	if(down == false)
+		return;
 
 	int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
 
@@ -73,24 +53,15 @@ void MapViewActions::clickLeft(tribool down, bool previousState)
 
 void MapViewActions::clickRight(tribool down, bool previousState)
 {
-	if(isSwiping)
-		return;
-
 	int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
 
 	if(down && context->isInMap(tile))
 		adventureInt->onTileRightClicked(tile);
 }
 
-void MapViewActions::clickMiddle(tribool down, bool previousState)
-{
-	handleSwipeStateChange(static_cast<bool>(down));
-}
-
 void MapViewActions::mouseMoved(const Point & cursorPosition)
 {
 	handleHover(cursorPosition);
-	handleSwipeMove(cursorPosition);
 }
 
 void MapViewActions::wheelScrolled(bool down, bool in)
@@ -100,49 +71,9 @@ void MapViewActions::wheelScrolled(bool down, bool in)
 	adventureInt->hotkeyZoom(down ? -1 : +1);
 }
 
-void MapViewActions::handleSwipeMove(const Point & cursorPosition)
+void MapViewActions::gesturePanning(const Point & distance)
 {
-	// unless swipe is enabled, swipe move only works with middle mouse button
-	if(!swipeEnabled() && !GH.isMouseButtonPressed(MouseButton::MIDDLE))
-		return;
-
-	// on mobile platforms with enabled swipe we use left button
-	if(swipeEnabled() && !GH.isMouseButtonPressed(MouseButton::LEFT))
-		return;
-
-	if(!isSwiping)
-	{
-		static constexpr int touchSwipeSlop = 16;
-		Point distance = (cursorPosition - swipeInitialRealPos);
-
-		// try to distinguish if this touch was meant to be a swipe or just fat-fingering press
-		if(std::abs(distance.x) + std::abs(distance.y) > touchSwipeSlop)
-			isSwiping = true;
-	}
-
-	if(isSwiping)
-	{
-		Point swipeTargetPosition = swipeInitialViewPos + swipeInitialRealPos - cursorPosition;
-		owner.onMapSwiped(swipeTargetPosition);
-	}
-}
-
-bool MapViewActions::handleSwipeStateChange(bool btnPressed)
-{
-	if(btnPressed)
-	{
-		swipeInitialRealPos = GH.getCursorPosition();
-		swipeInitialViewPos = model->getMapViewCenter();
-		return true;
-	}
-
-	if(isSwiping) // only accept this touch if it wasn't a swipe
-	{
-		owner.onMapSwipeEnded();
-		isSwiping = false;
-		return true;
-	}
-	return false;
+	owner.onMapSwiped(distance);
 }
 
 void MapViewActions::handleHover(const Point & cursorPosition)

+ 1 - 9
client/mapView/MapViewActions.h

@@ -18,19 +18,11 @@ class MapView;
 
 class MapViewActions : public CIntObject
 {
-	bool isSwiping;
-
-	Point swipeInitialViewPos;
-	Point swipeInitialRealPos;
-
 	MapView & owner;
 	std::shared_ptr<MapViewModel> model;
 	std::shared_ptr<IMapRendererContext> context;
 
 	void handleHover(const Point & cursorPosition);
-	void handleSwipeMove(const Point & cursorPosition);
-	bool handleSwipeStateChange(bool btnPressed);
-	bool swipeEnabled() const;
 
 public:
 	MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel> & model);
@@ -39,7 +31,7 @@ public:
 
 	void clickLeft(tribool down, bool previousState) override;
 	void clickRight(tribool down, bool previousState) override;
-	void clickMiddle(tribool down, bool previousState) override;
+	void gesturePanning(const Point & distance) override;
 	void hover(bool on) override;
 	void mouseMoved(const Point & cursorPosition) override;
 	void wheelScrolled(bool down, bool in) override;

+ 1 - 1
client/windows/GUIClasses.cpp

@@ -1788,7 +1788,7 @@ void CObjectListWindow::CItem::clickLeft(tribool down, bool previousState)
 		parent->changeSelection(index);
 }
 
-void CObjectListWindow::CItem::onDoubleClick()
+void CObjectListWindow::CItem::clickDouble()
 {
 	parent->elementSelected();
 }

+ 1 - 1
client/windows/GUIClasses.h

@@ -163,7 +163,7 @@ class CObjectListWindow : public CWindowObject
 
 		void select(bool on);
 		void clickLeft(tribool down, bool previousState) override;
-		void onDoubleClick() override;
+		void clickDouble() override;
 	};
 
 	std::function<void(int)> onSelect;//called when OK button is pressed, returns id of selected item.