diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index 1ae81fe31..2c366799a 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -79,6 +79,8 @@ "vcmi.battleOptions.animationsSpeed1.help": "Set animation speed to very slow", "vcmi.battleOptions.animationsSpeed5.help": "Set animation speed to very fast", "vcmi.battleOptions.animationsSpeed6.help": "Set animation speed to instantaneous", + "vcmi.battleOptions.touchscreenMode.hover": "Touchscreen mode", + "vcmi.battleOptions.touchscreenMode.help": "{Touchscreen mode}\n\nIf enabled, second click is required to confirm and execute action. This is more suitable for touchscreen devices.", "vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music", "vcmi.battleOptions.skipBattleIntroMusic.help": "{Skip Intro Music}\n\nAllow actions during the intro music that plays at the beginning of each battle", "vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately", diff --git a/client/battle/BattleActionsController.cpp b/client/battle/BattleActionsController.cpp index 18c31acb4..a3c47fd8f 100644 --- a/client/battle/BattleActionsController.cpp +++ b/client/battle/BattleActionsController.cpp @@ -115,7 +115,9 @@ BattleActionsController::BattleActionsController(BattleInterface & owner): owner(owner), selectedStack(nullptr), heroSpellToCast(nullptr) -{} +{ + touchscreenMode = settings["battle"]["touchscreenMode"].Bool(); +} void BattleActionsController::endCastingSpell() { @@ -826,6 +828,10 @@ void BattleActionsController::onHoverEnded() void BattleActionsController::onHexLeftClicked(BattleHex clickedHex) { + static BattleHex lastSelectedHex; + static BattleHex lastDirectionalHex; + static PossiblePlayerBattleAction::Actions lastSelectedAction; + if (owner.stacksController->getActiveStack() == nullptr) return; @@ -835,10 +841,25 @@ 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); - actionRealize(action, clickedHex); + if(!touchscreenMode || (lastSelectedAction == action.get() && lastSelectedHex == clickedHex && lastDirectionalHex == directionalHex)) + { + actionRealize(action, clickedHex); - GH.statusbar->clear(); + GH.statusbar->clear(); + } + else + { + lastSelectedAction = action.get(); + lastSelectedHex = clickedHex; + lastDirectionalHex = directionalHex; + } } void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterStack) @@ -994,3 +1015,8 @@ void BattleActionsController::pushFrontPossibleAction(PossiblePlayerBattleAction { possibleActions.insert(possibleActions.begin(), action); } + +void BattleActionsController::setTouchScreenMode(bool enabled) +{ + touchscreenMode = enabled; +} diff --git a/client/battle/BattleActionsController.h b/client/battle/BattleActionsController.h index afc12544c..21efe73cf 100644 --- a/client/battle/BattleActionsController.h +++ b/client/battle/BattleActionsController.h @@ -34,7 +34,10 @@ enum class MouseHoveredHexContext class BattleActionsController { BattleInterface & owner; - + + /// mouse or touchscreen click mode + bool touchscreenMode = false; + /// all actions possible to call at the moment by player std::vector possibleActions; @@ -129,4 +132,5 @@ public: /// inserts possible action in the beggining in order to prioritize it void pushFrontPossibleAction(PossiblePlayerBattleAction); + void setTouchScreenMode(bool enabled); }; diff --git a/client/windows/settings/BattleOptionsTab.cpp b/client/windows/settings/BattleOptionsTab.cpp index fdd82feb4..69a4ffa22 100644 --- a/client/windows/settings/BattleOptionsTab.cpp +++ b/client/windows/settings/BattleOptionsTab.cpp @@ -13,6 +13,7 @@ #include "CConfigHandler.h" #include "../../battle/BattleInterface.h" +#include "../../battle/BattleActionsController.h" #include "../../gui/CGuiHandler.h" #include "../../../lib/filesystem/ResourceID.h" #include "../../../lib/CGeneralTextHandler.h" @@ -53,6 +54,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner) { skipBattleIntroMusicChangedCallback(value); }); + addCallback("touchscreenModeChanged", [this, owner](bool value) + { + touchscreenModeChangedCallback(value, owner); + }); build(config); std::shared_ptr animationSpeedToggle = widget("animationSpeedPicker"); @@ -69,6 +74,9 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner) std::shared_ptr mouseShadowCheckbox = widget("mouseShadowCheckbox"); mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool()); + + std::shared_ptr touchscreenModeCheckbox = widget("touchscreenModeCheckbox"); + touchscreenModeCheckbox->setSelected(settings["battle"]["touchscreenMode"].Bool()); std::shared_ptr skipBattleIntroMusicCheckbox = widget("skipBattleIntroMusicCheckbox"); skipBattleIntroMusicCheckbox->setSelected(settings["gameTweaks"]["skipBattleIntroMusic"].Bool()); @@ -136,6 +144,14 @@ void BattleOptionsTab::mouseShadowChangedCallback(bool value) shadow->Bool() = value; } +void BattleOptionsTab::touchscreenModeChangedCallback(bool value, BattleInterface * parentBattleInterface) +{ + Settings touchcreenMode = settings.write["battle"]["touchscreenMode"]; + touchcreenMode->Bool() = value; + if(parentBattleInterface) + parentBattleInterface->actionsController->setTouchScreenMode(value); +} + void BattleOptionsTab::animationSpeedChangedCallback(int value) { Settings speed = settings.write["battle"]["speedFactor"]; diff --git a/client/windows/settings/BattleOptionsTab.h b/client/windows/settings/BattleOptionsTab.h index 0850b3773..77ef5e293 100644 --- a/client/windows/settings/BattleOptionsTab.h +++ b/client/windows/settings/BattleOptionsTab.h @@ -29,6 +29,7 @@ private: void showQueueChangedCallback(bool value, BattleInterface * parentBattleInterface); void queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface); void skipBattleIntroMusicChangedCallback(bool value); + void touchscreenModeChangedCallback(bool value, BattleInterface * parentBattleInterface); public: BattleOptionsTab(BattleInterface * owner = nullptr); }; diff --git a/config/schemas/settings.json b/config/schemas/settings.json index 4b60b32af..1d8710464 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -286,7 +286,7 @@ "type" : "object", "additionalProperties" : false, "default": {}, - "required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "showQueue", "queueSize" ], + "required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "showQueue", "queueSize", "touchscreenMode" ], "properties" : { "speedFactor" : { "type" : "number", @@ -300,6 +300,10 @@ "type" : "boolean", "default" : false }, + "touchscreenMode" : { + "type" : "boolean", + "default" : false + }, "stackRange" : { "type" : "boolean", "default" : true diff --git a/config/widgets/settings/battleOptionsTab.json b/config/widgets/settings/battleOptionsTab.json index f9fc78a0e..95bcd0d52 100644 --- a/config/widgets/settings/battleOptionsTab.json +++ b/config/widgets/settings/battleOptionsTab.json @@ -5,13 +5,13 @@ "name": "lineCreatureInfo", "type": "texture", "image": "settingsWindow/lineHorizontal", - "rect": { "x" : 5, "y" : 199, "w": 365, "h": 3} + "rect": { "x" : 5, "y" : 229, "w": 365, "h": 3} }, { "name": "lineAnimationSpeed", "type": "texture", "image": "settingsWindow/lineHorizontal", - "rect": { "x" : 5, "y" : 289, "w": 365, "h": 3} + "rect": { "x" : 5, "y" : 319, "w": 365, "h": 3} }, { @@ -28,7 +28,7 @@ }, { "text": "core.genrltxt.397", // Creature info - "position": {"x": 10, "y": 205} + "position": {"x": 10, "y": 235} } ] }, @@ -104,11 +104,11 @@ [ { "text": "core.genrltxt.402", // All Stats - "position": {"x": 45, "y": 235} + "position": {"x": 45, "y": 265} }, { "text": "core.genrltxt.403", // Spells only - "position": {"x": 45, "y": 265} + "position": {"x": 45, "y": 295} } ] }, @@ -116,13 +116,13 @@ "name": "creatureInfoAllPlaceholder", "type": "picture", "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 10, "y": 233}, + "position": {"x": 10, "y": 263}, }, { "name": "creatureInfoSpellsPlaceholder", "type": "picture", "image": "settingsWindow/checkBoxEmpty", - "position": {"x": 10, "y": 263}, + "position": {"x": 10, "y": 293}, }, { @@ -152,6 +152,10 @@ { "text": "vcmi.battleOptions.skipBattleIntroMusic.hover", "position": {"x": 45, "y": 175} + }, + { + "text": "vcmi.battleOptions.touchscreenMode.hover", + "position": {"x": 45, "y": 205} } ] }, @@ -194,6 +198,14 @@ "position": {"x": 10, "y": 173}, "callback": "skipBattleIntroMusicChanged" }, + { + "name": "touchscreenModeCheckbox", + "type": "toggleButton", + "image": "sysopchk.def", + "help": "vcmi.battleOptions.touchscreenMode", + "position": {"x": 10, "y": 203}, + "callback": "touchscreenModeChanged" + }, /////////////////////////////////////// Bottom section - Animation Speed and Turn Order { "name": "frameAnimationSpeed",