mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Implemented pinch gesture to scale adventure map
This commit is contained in:
parent
a08ff1e6ef
commit
0f2a339ab5
@ -204,7 +204,12 @@ void InputSourceTouch::handleUpdate()
|
||||
|
||||
Point InputSourceTouch::convertTouchToMouse(const SDL_TouchFingerEvent & tfinger)
|
||||
{
|
||||
return Point(tfinger.x * GH.screenDimensions().x, tfinger.y * GH.screenDimensions().y);
|
||||
return convertTouchToMouse(tfinger.x, tfinger.y);
|
||||
}
|
||||
|
||||
Point InputSourceTouch::convertTouchToMouse(float x, float y)
|
||||
{
|
||||
return Point(x * GH.screenDimensions().x, y * GH.screenDimensions().y);
|
||||
}
|
||||
|
||||
bool InputSourceTouch::hasTouchInputDevice() const
|
||||
@ -225,12 +230,51 @@ bool InputSourceTouch::isMouseButtonPressed(MouseButton button) const
|
||||
|
||||
void InputSourceTouch::emitPanningEvent(const SDL_TouchFingerEvent & tfinger)
|
||||
{
|
||||
Point distance(-tfinger.dx * GH.screenDimensions().x, -tfinger.dy * GH.screenDimensions().y);
|
||||
Point distance = convertTouchToMouse(-tfinger.dx, -tfinger.dy);
|
||||
|
||||
GH.events().dispatchGesturePanning(lastTapPosition, convertTouchToMouse(tfinger), distance);
|
||||
}
|
||||
|
||||
void InputSourceTouch::emitPinchEvent(const SDL_TouchFingerEvent & tfinger)
|
||||
{
|
||||
// TODO
|
||||
int fingers = SDL_GetNumTouchFingers(tfinger.touchId);
|
||||
|
||||
if (fingers < 2)
|
||||
return;
|
||||
|
||||
bool otherFingerFound = false;
|
||||
double otherX;
|
||||
double otherY;
|
||||
|
||||
for (int i = 0; i < fingers; ++i)
|
||||
{
|
||||
SDL_Finger * finger = SDL_GetTouchFinger(tfinger.touchId, i);
|
||||
|
||||
if (finger && finger->id != tfinger.fingerId)
|
||||
{
|
||||
otherX = finger->x * GH.screenDimensions().x;
|
||||
otherY = finger->y * GH.screenDimensions().y;
|
||||
otherFingerFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!otherFingerFound)
|
||||
return; // should be impossible, but better to avoid weird edge cases
|
||||
|
||||
float thisX = tfinger.x * GH.screenDimensions().x;
|
||||
float thisY = tfinger.y * GH.screenDimensions().y;
|
||||
float deltaX = tfinger.dx * GH.screenDimensions().x;
|
||||
float deltaY = tfinger.dy * GH.screenDimensions().y;
|
||||
|
||||
float oldX = thisX - deltaX - otherX;
|
||||
float oldY = thisY - deltaY - otherY;
|
||||
float newX = thisX - otherX;
|
||||
float newY = thisY - otherY;
|
||||
|
||||
double distanceOld = std::sqrt(oldX * oldX + oldY + oldY);
|
||||
double distanceNew = std::sqrt(newX * newX + newY + newY);
|
||||
|
||||
if (distanceOld > params.pinchSensitivityThreshold)
|
||||
GH.events().dispatchGesturePinch(lastTapPosition, distanceNew / distanceOld);
|
||||
}
|
||||
|
@ -81,6 +81,9 @@ struct TouchInputParameters
|
||||
/// moving finger for distance larger than specified will be qualified as panning gesture instead of long press
|
||||
uint32_t panningSensitivityThreshold = 10;
|
||||
|
||||
/// gesture will be qualified as pinch if distance between fingers is at least specified here
|
||||
uint32_t pinchSensitivityThreshold = 10;
|
||||
|
||||
bool useRelativeMode = false;
|
||||
};
|
||||
|
||||
@ -93,6 +96,7 @@ class InputSourceTouch
|
||||
Point lastTapPosition;
|
||||
|
||||
Point convertTouchToMouse(const SDL_TouchFingerEvent & current);
|
||||
Point convertTouchToMouse(float x, float y);
|
||||
|
||||
void emitPanningEvent(const SDL_TouchFingerEvent & tfinger);
|
||||
void emitPinchEvent(const SDL_TouchFingerEvent & tfinger);
|
||||
|
@ -254,6 +254,15 @@ void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, cons
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::dispatchGesturePinch(const Point & initialPosition, double distance)
|
||||
{
|
||||
for(auto it : panningInterested)
|
||||
{
|
||||
if (it->isPanning())
|
||||
it->gesturePinch(initialPosition, distance);
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::dispatchMouseMoved(const Point & position)
|
||||
{
|
||||
EventReceiversList newlyHovered;
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
void dispatchGesturePanningStarted(const Point & initialPosition);
|
||||
void dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition);
|
||||
void dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance);
|
||||
void dispatchGesturePinch(const Point & initialPosition, double distance);
|
||||
|
||||
/// Text input events
|
||||
void dispatchTextInput(const std::string & text);
|
||||
|
@ -42,6 +42,8 @@ protected:
|
||||
/// Called when user pans screen by specified distance
|
||||
virtual void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) {}
|
||||
|
||||
virtual void gesturePinch(const Point & centerPosition, double lastUpdateFactor) {}
|
||||
|
||||
virtual void wheelScrolled(int distance) {}
|
||||
virtual void mouseMoved(const Point & cursorPosition) {}
|
||||
|
||||
|
@ -20,11 +20,15 @@
|
||||
#include "../gui/CursorHandler.h"
|
||||
#include "../gui/MouseButton.h"
|
||||
|
||||
#include "../CPlayerInterface.h"
|
||||
#include "../adventureMap/CInGameConsole.h"
|
||||
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
|
||||
MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewModel> & model)
|
||||
: model(model)
|
||||
, owner(owner)
|
||||
, pinchZoomFactor(1.0)
|
||||
{
|
||||
pos.w = model->getPixelsVisibleDimensions().x;
|
||||
pos.h = model->getPixelsVisibleDimensions().y;
|
||||
@ -66,7 +70,7 @@ void MapViewActions::mouseMoved(const Point & cursorPosition)
|
||||
|
||||
void MapViewActions::wheelScrolled(int distance)
|
||||
{
|
||||
adventureInt->hotkeyZoom(distance);
|
||||
adventureInt->hotkeyZoom(distance * 4);
|
||||
}
|
||||
|
||||
void MapViewActions::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
||||
@ -74,6 +78,24 @@ void MapViewActions::gesturePanning(const Point & initialPosition, const Point &
|
||||
owner.onMapSwiped(lastUpdateDistance);
|
||||
}
|
||||
|
||||
void MapViewActions::gesturePinch(const Point & centerPosition, double lastUpdateFactor)
|
||||
{
|
||||
double newZoom = pinchZoomFactor * lastUpdateFactor;
|
||||
|
||||
int newZoomSteps = std::round(std::log(newZoom) / std::log(1.01));
|
||||
int oldZoomSteps = std::round(std::log(pinchZoomFactor) / std::log(1.01));
|
||||
|
||||
if (newZoomSteps != oldZoomSteps)
|
||||
adventureInt->hotkeyZoom(newZoomSteps - oldZoomSteps);
|
||||
|
||||
pinchZoomFactor = newZoom;
|
||||
}
|
||||
|
||||
void MapViewActions::panning(bool on, const Point & initialPosition, const Point & finalPosition)
|
||||
{
|
||||
pinchZoomFactor = 1.0;
|
||||
}
|
||||
|
||||
void MapViewActions::handleHover(const Point & cursorPosition)
|
||||
{
|
||||
int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
|
||||
|
@ -22,6 +22,8 @@ class MapViewActions : public CIntObject
|
||||
std::shared_ptr<MapViewModel> model;
|
||||
std::shared_ptr<IMapRendererContext> context;
|
||||
|
||||
double pinchZoomFactor;
|
||||
|
||||
void handleHover(const Point & cursorPosition);
|
||||
|
||||
public:
|
||||
@ -32,7 +34,9 @@ public:
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
|
||||
void gesturePinch(const Point & centerPosition, double lastUpdateFactor) override;
|
||||
void hover(bool on) override;
|
||||
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
||||
void mouseMoved(const Point & cursorPosition) override;
|
||||
void wheelScrolled(int distance) override;
|
||||
};
|
||||
|
@ -91,9 +91,9 @@ void MapViewController::modifyTileSize(int stepsChange)
|
||||
// so, zooming in for 5 steps will put game at 1.1^5 = 1.61 scale
|
||||
// try to determine current zooming level and change it by requested number of steps
|
||||
double currentZoomFactor = model->getSingleTileSize().x / 32.0;
|
||||
double currentZoomSteps = std::round(std::log(currentZoomFactor) / std::log(1.1));
|
||||
double currentZoomSteps = std::round(std::log(currentZoomFactor) / std::log(1.01));
|
||||
double newZoomSteps = stepsChange != 0 ? currentZoomSteps + stepsChange : stepsChange;
|
||||
double newZoomFactor = std::pow(1.1, newZoomSteps);
|
||||
double newZoomFactor = std::pow(1.01, newZoomSteps);
|
||||
|
||||
Point currentZoom = model->getSingleTileSize();
|
||||
Point desiredZoom = Point(32,32) * newZoomFactor;
|
||||
|
Loading…
x
Reference in New Issue
Block a user