1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-25 00:37:24 +02:00

Test version of swipe gesture for in-combat attacks

This commit is contained in:
Ivan Savenko
2023-05-31 00:33:10 +03:00
parent 70155b48e1
commit b20109c830
20 changed files with 79 additions and 104 deletions

View File

@ -117,7 +117,6 @@ BattleActionsController::BattleActionsController(BattleInterface & owner):
selectedStack(nullptr),
heroSpellToCast(nullptr)
{
touchscreenMode = settings["battle"]["touchscreenMode"].Bool();
}
void BattleActionsController::endCastingSpell()
@ -826,10 +825,6 @@ void BattleActionsController::onHoverEnded()
void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
{
static BattleHex lastSelectedHex;
static BattleHex lastDirectionalHex;
static PossiblePlayerBattleAction::Actions lastSelectedAction;
if (owner.stacksController->getActiveStack() == nullptr)
return;
@ -840,25 +835,9 @@ void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
if (!actionIsLegal(action, clickedHex))
return;
auto directionalHex = lastDirectionalHex;
if(action.get() == PossiblePlayerBattleAction::ATTACK
|| action.get() == PossiblePlayerBattleAction::WALK_AND_ATTACK
|| action.get() == PossiblePlayerBattleAction::ATTACK_AND_RETURN)
directionalHex = owner.fieldController->fromWhichHexAttack(clickedHex);
if(!touchscreenMode || (lastSelectedAction == action.get() && lastSelectedHex == clickedHex && lastDirectionalHex == directionalHex))
{
actionRealize(action, clickedHex);
GH.statusbar()->clear();
}
else
{
lastSelectedAction = action.get();
lastSelectedHex = clickedHex;
lastDirectionalHex = directionalHex;
}
}
void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterStack)
{
@ -1018,8 +997,3 @@ void BattleActionsController::pushFrontPossibleAction(PossiblePlayerBattleAction
{
possibleActions.insert(possibleActions.begin(), action);
}
void BattleActionsController::setTouchScreenMode(bool enabled)
{
touchscreenMode = enabled;
}

View File

@ -35,9 +35,6 @@ class BattleActionsController
{
BattleInterface & owner;
/// mouse or touchscreen click mode
bool touchscreenMode = false;
/// all actions possible to call at the moment by player
std::vector<PossiblePlayerBattleAction> possibleActions;
@ -131,6 +128,4 @@ public:
/// inserts possible action in the beggining in order to prioritize it
void pushFrontPossibleAction(PossiblePlayerBattleAction);
void setTouchScreenMode(bool enabled);
};

View File

@ -67,7 +67,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
updateAccessibleHexes();
addUsedEvents(LCLICK | RCLICK | MOVE | TIME);
addUsedEvents(LCLICK | RCLICK | MOVE | TIME | GESTURE_PANNING);
}
void BattleFieldController::activate()
@ -88,16 +88,39 @@ void BattleFieldController::createHeroes()
owner.defendingHero = std::make_shared<BattleHero>(owner, owner.defendingHeroInstance, true);
}
void BattleFieldController::panning(bool on, const Point & initialPosition, const Point & finalPosition)
{
if (!on && pos.isInside(finalPosition))
clickLeft(false, false);
}
void BattleFieldController::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
if (pos.isInside(currentPosition))
{
hoveredHex = getHexAtPosition(initialPosition);
currentAttackDirection = selectAttackDirection(getHoveredHex(), currentPosition);
owner.actionsController->onHexHovered(getHoveredHex());
}
else
{
hoveredHex = BattleHex::INVALID;
}
}
void BattleFieldController::mouseMoved(const Point & cursorPosition)
{
hoveredHex = getHexAtPosition(cursorPosition);
currentAttackDirection = selectAttackDirection(getHoveredHex(), cursorPosition);
if (!pos.isInside(cursorPosition))
{
owner.actionsController->onHoverEnded();
return;
}
BattleHex selectedHex = getHoveredHex();
owner.actionsController->onHexHovered(selectedHex);
owner.actionsController->onHexHovered(getHoveredHex());
}
void BattleFieldController::clickLeft(tribool down, bool previousState)
@ -233,7 +256,7 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesForActiveStack()
auto hoveredHex = getHoveredHex();
std::set<BattleHex> set = owner.curInt->cb->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex, attackingHex);
std::set<BattleHex> set = owner.curInt->cb->battleGetAttackedHexes(owner.stacksController->getActiveStack(), hoveredHex);
for(BattleHex hex : set)
result.insert(hex);
@ -390,8 +413,11 @@ bool BattleFieldController::isPixelInHex(Point const & position)
BattleHex BattleFieldController::getHoveredHex()
{
Point hoverPos = GH.getCursorPosition();
return hoveredHex;
}
BattleHex BattleFieldController::getHexAtPosition(Point hoverPos)
{
if (owner.attackingHero)
{
if (owner.attackingHero->pos.isInside(hoverPos))
@ -404,7 +430,6 @@ BattleHex BattleFieldController::getHoveredHex()
return BattleHex::HERO_DEFENDER;
}
for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h)
{
Rect hexPosition = hexPositionAbsolute(h);
@ -421,8 +446,6 @@ BattleHex BattleFieldController::getHoveredHex()
void BattleFieldController::setBattleCursor(BattleHex myNumber)
{
Point cursorPos = CCS->curh->position();
std::vector<Cursor::Combat> sectorCursor = {
Cursor::Combat::HIT_SOUTHEAST,
Cursor::Combat::HIT_SOUTHWEST,
@ -434,7 +457,7 @@ void BattleFieldController::setBattleCursor(BattleHex myNumber)
Cursor::Combat::HIT_NORTH,
};
auto direction = static_cast<size_t>(selectAttackDirection(myNumber, cursorPos));
auto direction = static_cast<size_t>(currentAttackDirection);
assert(direction != -1);
if (direction != -1)
@ -517,7 +540,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
{
BattleHex::EDir direction = selectAttackDirection(attackTarget, CCS->curh->position());
BattleHex::EDir direction = currentAttackDirection;
const CStack * attacker = owner.stacksController->getActiveStack();

View File

@ -39,8 +39,11 @@ class BattleFieldController : public CIntObject
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
std::unique_ptr<Canvas> backgroundWithHexes;
/// hex from which the stack would perform attack with current cursor
BattleHex attackingHex;
/// direction which will be used to perform attack with current cursor position
BattleHex::EDir currentAttackDirection;
/// hex currently under mouse hover
BattleHex hoveredHex;
/// hexes to which currently active stack can move
std::vector<BattleHex> occupiableHexes;
@ -61,8 +64,15 @@ class BattleFieldController : public CIntObject
void showHighlightedHexes(Canvas & canvas);
void updateAccessibleHexes();
BattleHex getHexAtPosition(Point hoverPosition);
/// Checks whether selected pixel is transparent, uses local coordinates of a hex
bool isPixelInHex(Point const & position);
BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void mouseMoved(const Point & cursorPosition) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
@ -73,6 +83,7 @@ class BattleFieldController : public CIntObject
void tick(uint32_t msPassed) override;
bool receiveEvent(const Point & position, int eventType) const override;
public:
BattleFieldController(BattleInterface & owner);
@ -87,9 +98,6 @@ public:
/// Returns position of hex relative to game window
Rect hexPositionAbsolute(BattleHex hex) const;
/// Checks whether selected pixel is transparent, uses local coordinates of a hex
bool isPixelInHex(Point const & position);
/// Returns ID of currently hovered hex or BattleHex::INVALID if none
BattleHex getHoveredHex();

View File

@ -27,7 +27,7 @@ void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motio
GH.input().setCursorPosition(newPosition);
if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE))
GH.events().dispatchGesturePanning(distance);
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
mouseButtonsMask = motion.state;
}
@ -48,6 +48,7 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
break;
case SDL_BUTTON_MIDDLE:
middleClickPosition = position;
GH.events().dispatchGesturePanningStarted(position);
break;
}
@ -71,7 +72,7 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
break;
case SDL_BUTTON_MIDDLE:
GH.events().dispatchGesturePanningEnded();
GH.events().dispatchGesturePanningEnded(middleClickPosition, position);
break;
}
}

View File

@ -10,6 +10,8 @@
#pragma once
#include "../../lib/Point.h"
struct SDL_MouseWheelEvent;
struct SDL_MouseMotionEvent;
struct SDL_MouseButtonEvent;
@ -19,6 +21,7 @@ enum class MouseButton;
/// Class that handles mouse input from SDL events
class InputSourceMouse
{
Point middleClickPosition;
int mouseButtonsMask = 0;
public:
void handleEventMouseMotion(const SDL_MouseMotionEvent & current);

View File

@ -61,9 +61,7 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
}
case TouchState::TAP_DOWN_SHORT:
{
GH.input().setCursorPosition(convertTouchToMouse(tfinger));
Point distance = GH.getCursorPosition() - lastTapPosition;
Point distance = convertTouchToMouse(tfinger) - lastTapPosition;
if ( std::abs(distance.x) > params.panningSensitivityThreshold || std::abs(distance.y) > params.panningSensitivityThreshold)
state = TouchState::TAP_DOWN_PANNING;
break;
@ -104,8 +102,8 @@ void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinge
}
case TouchState::IDLE:
{
GH.input().setCursorPosition(convertTouchToMouse(tfinger));
lastTapPosition = GH.getCursorPosition();
lastTapPosition = convertTouchToMouse(tfinger);
GH.input().setCursorPosition(lastTapPosition);
GH.events().dispatchGesturePanningStarted(lastTapPosition);
state = TouchState::TAP_DOWN_SHORT;
break;
@ -155,7 +153,7 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
}
case TouchState::TAP_DOWN_PANNING:
{
GH.events().dispatchGesturePanningEnded();
GH.events().dispatchGesturePanningEnded(lastTapPosition, convertTouchToMouse(tfinger));
state = TouchState::IDLE;
break;
}
@ -165,7 +163,7 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
state = TouchState::TAP_DOWN_PANNING;
if (SDL_GetNumTouchFingers(tfinger.touchId) == 0)
{
GH.events().dispatchGesturePanningEnded();
GH.events().dispatchGesturePanningEnded(lastTapPosition, convertTouchToMouse(tfinger));
state = TouchState::IDLE;
}
break;
@ -229,7 +227,7 @@ void InputSourceTouch::emitPanningEvent(const SDL_TouchFingerEvent & tfinger)
{
Point distance(-tfinger.dx * GH.screenDimensions().x, -tfinger.dy * GH.screenDimensions().y);
GH.events().dispatchGesturePanning(distance);
GH.events().dispatchGesturePanning(lastTapPosition, convertTouchToMouse(tfinger), distance);
}
void InputSourceTouch::emitPinchEvent(const SDL_TouchFingerEvent & tfinger)

View File

@ -64,11 +64,6 @@ CursorHandler::CursorHandler()
CursorHandler::~CursorHandler() = default;
Point CursorHandler::position() const
{
return pos;
}
void CursorHandler::changeGraphic(Cursor::Type type, size_t index)
{
assert(dndObject == nullptr);

View File

@ -150,9 +150,6 @@ public:
void dragAndDropCursor(std::string path, size_t index);
/// Returns current position of the cursor
Point position() const;
/// Changes cursor to specified index
void set(Cursor::Default index);
void set(Cursor::Map index);

View File

@ -225,32 +225,32 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
{
if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE_PANNING))
{
it->panning(true);
it->panning(true, initialPosition, initialPosition);
it->panningState = true;
}
}
}
void EventDispatcher::dispatchGesturePanningEnded()
void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
{
for(auto it : panningInterested)
{
if (it->isPanning())
{
it->panning(false);
it->panning(false, initialPosition, finalPosition);
it->panningState = false;
}
}
}
void EventDispatcher::dispatchGesturePanning(const Point & distance)
void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
auto copied = panningInterested;
for(auto it : copied)
{
if (it->isPanning())
it->gesturePanning(distance);
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
}
}

View File

@ -63,8 +63,8 @@ public:
void dispatchMouseMoved(const Point & distance);
void dispatchGesturePanningStarted(const Point & initialPosition);
void dispatchGesturePanningEnded();
void dispatchGesturePanning(const Point & distance);
void dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition);
void dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance);
/// Text input events
void dispatchTextInput(const std::string & text);

View File

@ -40,7 +40,7 @@ protected:
virtual void clickDouble() {}
/// Called when user pans screen by specified distance
virtual void gesturePanning(const Point & distanceDelta) {}
virtual void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) {}
virtual void wheelScrolled(int distance) {}
virtual void mouseMoved(const Point & cursorPosition) {}
@ -49,7 +49,7 @@ protected:
virtual void hover(bool on) {}
/// Called when UI element panning gesture status changes
virtual void panning(bool on) {}
virtual void panning(bool on, const Point & initialPosition, const Point & finalPosition) {}
virtual void textInputed(const std::string & enteredText) {}
virtual void textEdited(const std::string & enteredText) {}

View File

@ -69,9 +69,9 @@ void MapViewActions::wheelScrolled(int distance)
adventureInt->hotkeyZoom(distance);
}
void MapViewActions::gesturePanning(const Point & distance)
void MapViewActions::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
owner.onMapSwiped(distance);
owner.onMapSwiped(lastUpdateDistance);
}
void MapViewActions::handleHover(const Point & cursorPosition)

View File

@ -31,7 +31,7 @@ public:
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void gesturePanning(const Point & distance) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void hover(bool on) override;
void mouseMoved(const Point & cursorPosition) override;
void wheelScrolled(int distance) override;

View File

@ -20,7 +20,7 @@ Scrollable::Scrollable(int used, Point position, Orientation orientation)
{
}
void Scrollable::panning(bool on)
void Scrollable::panning(bool on, const Point & initialPosition, const Point & finalPosition)
{
panningDistanceAccumulated = 0;
}
@ -33,12 +33,12 @@ void Scrollable::wheelScrolled(int distance)
scrollBy(-distance * scrollStep);
}
void Scrollable::gesturePanning(const Point & distanceDelta)
void Scrollable::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
if (orientation == Orientation::HORIZONTAL)
panningDistanceAccumulated += -distanceDelta.x;
panningDistanceAccumulated += -lastUpdateDistance.x;
else
panningDistanceAccumulated += distanceDelta.y;
panningDistanceAccumulated += lastUpdateDistance.y;
if (-panningDistanceAccumulated > panningDistanceSingle )
{

View File

@ -33,9 +33,9 @@ class Scrollable : public CIntObject
protected:
Scrollable(int used, Point position, Orientation orientation);
void panning(bool on) override;
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
void wheelScrolled(int distance) override;
void gesturePanning(const Point & distanceDelta) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
int getScrollStep() const;
Orientation getOrientation() const;

View File

@ -172,8 +172,6 @@ void BattleOptionsTab::touchscreenModeChangedCallback(bool value, BattleInterfac
{
Settings touchcreenMode = settings.write["battle"]["touchscreenMode"];
touchcreenMode->Bool() = value;
if(parentBattleInterface)
parentBattleInterface->actionsController->setTouchScreenMode(value);
}
void BattleOptionsTab::animationSpeedChangedCallback(int value)

View File

@ -297,7 +297,7 @@
},
"touchscreenMode" : {
"type" : "boolean",
"default" : false
"default" : true
},
"stackRange" : {
"type" : "boolean",

View File

@ -102,7 +102,6 @@ void FirstLaunchView::on_comboBoxLanguage_currentIndexChanged(int index)
void FirstLaunchView::enterSetup()
{
setupPlatformSettings();
Languages::fillLanguages(ui->listWidgetLanguage, false);
}
@ -159,19 +158,6 @@ void FirstLaunchView::exitSetup()
mainWindow->exitSetup();
}
// Initial platform-dependend settings
void FirstLaunchView::setupPlatformSettings()
{
#if defined(VCMI_MOBILE)
bool touchscreenMode = true;
#else
bool touchscreenMode = false;
#endif
Settings node = settings.write["battle"]["touchscreenMode"];
node->Bool() = touchscreenMode;
}
// Tab Language
void FirstLaunchView::languageSelected(const QString & selectedLanguage)
{

View File

@ -38,9 +38,6 @@ class FirstLaunchView : public QWidget
void activateTabModPreset();
void exitSetup();
// Initial platform-dependend settings
void setupPlatformSettings();
// Tab Language
void languageSelected(const QString & languageCode);