Merge pull request #2292 from IvanSavenko/radial_wheel_garrison
Radial wheel for army management
BIN
Mods/vcmi/Data/radialMenu/heroMove.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
Mods/vcmi/Data/radialMenu/heroSwap.png
Normal file
After Width: | Height: | Size: 511 B |
BIN
Mods/vcmi/Data/radialMenu/itemEmpty.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Mods/vcmi/Data/radialMenu/itemInactive.png
Normal file
After Width: | Height: | Size: 676 B |
BIN
Mods/vcmi/Data/radialMenu/stackInfo.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
Mods/vcmi/Data/radialMenu/stackMerge.png
Normal file
After Width: | Height: | Size: 678 B |
BIN
Mods/vcmi/Data/radialMenu/stackSplitDialog.png
Normal file
After Width: | Height: | Size: 490 B |
BIN
Mods/vcmi/Data/radialMenu/stackSplitEqual.png
Normal file
After Width: | Height: | Size: 934 B |
BIN
Mods/vcmi/Data/radialMenu/stackSplitOne.png
Normal file
After Width: | Height: | Size: 914 B |
BIN
Mods/vcmi/Data/radialMenu/statusBar.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
@ -30,6 +30,13 @@
|
|||||||
"vcmi.capitalColors.6" : "Teal",
|
"vcmi.capitalColors.6" : "Teal",
|
||||||
"vcmi.capitalColors.7" : "Pink",
|
"vcmi.capitalColors.7" : "Pink",
|
||||||
|
|
||||||
|
"vcmi.radialWheel.mergeSameUnit" : "Merge same creatures",
|
||||||
|
"vcmi.radialWheel.showUnitInformation" : "Show creature information",
|
||||||
|
"vcmi.radialWheel.splitSingleUnit" : "Split off single creature",
|
||||||
|
"vcmi.radialWheel.splitUnitEqually" : "Split creatures equally",
|
||||||
|
"vcmi.radialWheel.moveUnit" : "Move creatures to another army",
|
||||||
|
"vcmi.radialWheel.splitUnit" : "Split creature to another slot",
|
||||||
|
|
||||||
"vcmi.mainMenu.tutorialNotImplemented" : "Sorry, tutorial is not implemented yet\n",
|
"vcmi.mainMenu.tutorialNotImplemented" : "Sorry, tutorial is not implemented yet\n",
|
||||||
"vcmi.mainMenu.highscoresNotImplemented" : "Sorry, high scores menu is not implemented yet\n",
|
"vcmi.mainMenu.highscoresNotImplemented" : "Sorry, high scores menu is not implemented yet\n",
|
||||||
"vcmi.mainMenu.serverConnecting" : "Connecting...",
|
"vcmi.mainMenu.serverConnecting" : "Connecting...",
|
||||||
@ -124,8 +131,8 @@
|
|||||||
"vcmi.battleOptions.showStickyHeroInfoWindows.help": "{Show heroes statistics windows}\n\nPermanently toggle on heroes statistics windows that show primary stats and spell points.",
|
"vcmi.battleOptions.showStickyHeroInfoWindows.help": "{Show heroes statistics windows}\n\nPermanently toggle on heroes statistics windows that show primary stats and spell points.",
|
||||||
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music",
|
"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.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",
|
|
||||||
|
|
||||||
|
"vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",
|
||||||
"vcmi.battleWindow.damageEstimation.melee" : "Attack %CREATURE (%DAMAGE).",
|
"vcmi.battleWindow.damageEstimation.melee" : "Attack %CREATURE (%DAMAGE).",
|
||||||
"vcmi.battleWindow.damageEstimation.meleeKills" : "Attack %CREATURE (%DAMAGE, %KILLS).",
|
"vcmi.battleWindow.damageEstimation.meleeKills" : "Attack %CREATURE (%DAMAGE, %KILLS).",
|
||||||
"vcmi.battleWindow.damageEstimation.ranged" : "Shoot %CREATURE (%SHOTS, %DAMAGE).",
|
"vcmi.battleWindow.damageEstimation.ranged" : "Shoot %CREATURE (%SHOTS, %DAMAGE).",
|
||||||
|
@ -13,14 +13,41 @@
|
|||||||
"vcmi.adventureMap.monsterThreat.levels.10" : "Смертельна",
|
"vcmi.adventureMap.monsterThreat.levels.10" : "Смертельна",
|
||||||
"vcmi.adventureMap.monsterThreat.levels.11" : "Неможлива",
|
"vcmi.adventureMap.monsterThreat.levels.11" : "Неможлива",
|
||||||
|
|
||||||
"vcmi.adventureMap.moveCostDetails" : "Очки руху - Вартість: %TURNS ходів + %POINTS очок. Залишок очок: %REMAINING",
|
|
||||||
"vcmi.adventureMap.moveCostDetailsNoTurns" : "Очки руху - Вартість: %POINTS очок, Залишок очок: %REMAINING",
|
|
||||||
|
|
||||||
"vcmi.adventureMap.confirmRestartGame" : "Ви впевнені, що хочете перезапустити гру?",
|
"vcmi.adventureMap.confirmRestartGame" : "Ви впевнені, що хочете перезапустити гру?",
|
||||||
"vcmi.adventureMap.noTownWithMarket" : "Немає доступних ринків!",
|
"vcmi.adventureMap.noTownWithMarket" : "Немає доступних ринків!",
|
||||||
"vcmi.adventureMap.noTownWithTavern" : "Немає доступного міста з таверною!",
|
"vcmi.adventureMap.noTownWithTavern" : "Немає доступного міста з таверною!",
|
||||||
"vcmi.adventureMap.spellUnknownProblem" : "Невідома проблема з цим заклинанням, більше інформації немає.",
|
"vcmi.adventureMap.spellUnknownProblem" : "Невідома проблема з цим заклинанням, більше інформації немає.",
|
||||||
"vcmi.adventureMap.playerAttacked" : "Гравця атаковано: %s",
|
"vcmi.adventureMap.playerAttacked" : "Гравця атаковано: %s",
|
||||||
|
"vcmi.adventureMap.moveCostDetails" : "Очки руху - Вартість: %TURNS ходів + %POINTS очок. Залишок очок: %REMAINING",
|
||||||
|
"vcmi.adventureMap.moveCostDetailsNoTurns" : "Очки руху - Вартість: %POINTS очок, Залишок очок: %REMAINING",
|
||||||
|
|
||||||
|
"vcmi.capitalColors.0" : "Червоний",
|
||||||
|
"vcmi.capitalColors.1" : "Синій",
|
||||||
|
"vcmi.capitalColors.2" : "Сірий",
|
||||||
|
"vcmi.capitalColors.3" : "Зелений",
|
||||||
|
"vcmi.capitalColors.4" : "Оранжевий",
|
||||||
|
"vcmi.capitalColors.5" : "Бордовий",
|
||||||
|
"vcmi.capitalColors.6" : "Сизий",
|
||||||
|
"vcmi.capitalColors.7" : "Рожевий",
|
||||||
|
|
||||||
|
"vcmi.radialWheel.mergeSameUnit" : "Об'єднати однакових істот",
|
||||||
|
"vcmi.radialWheel.showUnitInformation" : "Показати відомості про істоту",
|
||||||
|
"vcmi.radialWheel.splitSingleUnit" : "Відділити одну істоту",
|
||||||
|
"vcmi.radialWheel.splitUnitEqually" : "Розділити істот порівну",
|
||||||
|
"vcmi.radialWheel.moveUnit" : "Перемістити істоту до іншої армії",
|
||||||
|
"vcmi.radialWheel.splitUnit" : "Розділити істоту в інший слот",
|
||||||
|
|
||||||
|
"vcmi.mainMenu.tutorialNotImplemented" : "Вибачте, навчання ще не реалізовано\n",
|
||||||
|
"vcmi.mainMenu.highscoresNotImplemented" : "Вибачте, таблицю рекордів ще не реалізовано\n",
|
||||||
|
"vcmi.mainMenu.serverConnecting" : "Підключення...",
|
||||||
|
"vcmi.mainMenu.serverAddressEnter" : "Вкажіть адресу:",
|
||||||
|
"vcmi.mainMenu.serverClosing" : "Завершення...",
|
||||||
|
"vcmi.mainMenu.hostTCP" : "Створити TCP/IP гру",
|
||||||
|
"vcmi.mainMenu.joinTCP" : "Приєднатися до TCP/IP гри",
|
||||||
|
"vcmi.mainMenu.playerName" : "Гравець",
|
||||||
|
|
||||||
|
"vcmi.lobby.filename" : "Назва файлу",
|
||||||
|
"vcmi.lobby.creationDate" : "Дата створення",
|
||||||
|
|
||||||
"vcmi.server.errors.existingProcess" : "Працює інший процес vcmiserver, будь ласка, спочатку завершіть його",
|
"vcmi.server.errors.existingProcess" : "Працює інший процес vcmiserver, будь ласка, спочатку завершіть його",
|
||||||
"vcmi.server.errors.modsIncompatibility" : "Потрібні модифікації для завантаження гри:",
|
"vcmi.server.errors.modsIncompatibility" : "Потрібні модифікації для завантаження гри:",
|
||||||
@ -57,6 +84,8 @@
|
|||||||
"vcmi.systemOptions.longTouchMenu.entry" : "%d мілісекунд",
|
"vcmi.systemOptions.longTouchMenu.entry" : "%d мілісекунд",
|
||||||
"vcmi.systemOptions.framerateButton.hover" : "Лічильник кадрів",
|
"vcmi.systemOptions.framerateButton.hover" : "Лічильник кадрів",
|
||||||
"vcmi.systemOptions.framerateButton.help" : "{Лічильник кадрів}\n\n Перемикає видимість лічильника кадрів на секунду у кутку ігрового вікна",
|
"vcmi.systemOptions.framerateButton.help" : "{Лічильник кадрів}\n\n Перемикає видимість лічильника кадрів на секунду у кутку ігрового вікна",
|
||||||
|
"vcmi.systemOptions.hapticFeedbackButton.hover" : "Тактильний відгук",
|
||||||
|
"vcmi.systemOptions.hapticFeedbackButton.help" : "{Тактильний відгук}\n\Використовувати вібрацію при використанні сенсорного екрану",
|
||||||
|
|
||||||
"vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна",
|
"vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна",
|
||||||
"vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу",
|
"vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу",
|
||||||
@ -68,6 +97,8 @@
|
|||||||
"vcmi.adventureOptions.showGrid.help" : "{Показувати сітку}\n\n Відображає сітку, що показує межі між клітинками на мапі пригод.",
|
"vcmi.adventureOptions.showGrid.help" : "{Показувати сітку}\n\n Відображає сітку, що показує межі між клітинками на мапі пригод.",
|
||||||
"vcmi.adventureOptions.borderScroll.hover" : "Прокрутка по краю",
|
"vcmi.adventureOptions.borderScroll.hover" : "Прокрутка по краю",
|
||||||
"vcmi.adventureOptions.borderScroll.help" : "{{Прокрутка по краю}\n\nПрокручувати мапу пригод, коли курсор знаходиться біля краю вікна. Цю функцію можна вимкнути, утримуючи клавішу CTRL.",
|
"vcmi.adventureOptions.borderScroll.help" : "{{Прокрутка по краю}\n\nПрокручувати мапу пригод, коли курсор знаходиться біля краю вікна. Цю функцію можна вимкнути, утримуючи клавішу CTRL.",
|
||||||
|
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Керування істотами у вікні статусу",
|
||||||
|
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Керування істотами у вікні статусу}\n\nДозволяє впорядковувати істот у вікні статусу замість циклічного перемикання між типовими компонентами",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.hover" : "Переміщення мапи лівою кнопкою",
|
"vcmi.adventureOptions.leftButtonDrag.hover" : "Переміщення мапи лівою кнопкою",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.help" : "{Переміщення мапи лівою кнопкою}\n\nЯкщо увімкнено, переміщення миші з натиснутою лівою кнопкою буде перетягувати мапу пригод",
|
"vcmi.adventureOptions.leftButtonDrag.help" : "{Переміщення мапи лівою кнопкою}\n\nЯкщо увімкнено, переміщення миші з натиснутою лівою кнопкою буде перетягувати мапу пригод",
|
||||||
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
|
"vcmi.adventureOptions.mapScrollSpeed1.hover": "",
|
||||||
@ -96,11 +127,12 @@
|
|||||||
"vcmi.battleOptions.movementHighlightOnHover.help": "{Підсвічувати зону руху істоти}\n\nПідсвічувати можливу зону руху істоти при наведенні курсора миші на неї",
|
"vcmi.battleOptions.movementHighlightOnHover.help": "{Підсвічувати зону руху істоти}\n\nПідсвічувати можливу зону руху істоти при наведенні курсора миші на неї",
|
||||||
"vcmi.battleOptions.rangeLimitHighlightOnHover.hover": "Межа повного шкоди пострілом",
|
"vcmi.battleOptions.rangeLimitHighlightOnHover.hover": "Межа повного шкоди пострілом",
|
||||||
"vcmi.battleOptions.rangeLimitHighlightOnHover.help": "{Межа повного шкоди пострілом}\n\nПідсвічувати зону у якій створіння може завдавати максимальної шкоди пострілом при наведенні на неї курсору миші.",
|
"vcmi.battleOptions.rangeLimitHighlightOnHover.help": "{Межа повного шкоди пострілом}\n\nПідсвічувати зону у якій створіння може завдавати максимальної шкоди пострілом при наведенні на неї курсору миші.",
|
||||||
|
"vcmi.battleOptions.showStickyHeroInfoWindows.hover": "Показувати вікно інформації героя",
|
||||||
|
"vcmi.battleOptions.showStickyHeroInfoWindows.help": "{Показувати вікно інформації героя}\n\nЗавжди показувати вікно статистики героїв, що відображає первинні параметри та очки заклинань.",
|
||||||
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Пропускати вступну музику",
|
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Пропускати вступну музику",
|
||||||
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Пропускати вступну музику}\n\n Пропускати коротку музику, яка грає на початку кожної битви перед початком дії. Також можна пропустити, натиснувши клавішу ESC.",
|
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Пропускати вступну музику}\n\n Пропускати коротку музику, яка грає на початку кожної битви перед початком дії. Також можна пропустити, натиснувши клавішу ESC.",
|
||||||
|
|
||||||
"vcmi.battleWindow.pressKeyToSkipIntro" : "Натисніть будь-яку клавішу, щоб розпочати бій",
|
"vcmi.battleWindow.pressKeyToSkipIntro" : "Натисніть будь-яку клавішу, щоб розпочати бій",
|
||||||
|
|
||||||
"vcmi.battleWindow.damageEstimation.melee" : "Атакувати %CREATURE (%DAMAGE).",
|
"vcmi.battleWindow.damageEstimation.melee" : "Атакувати %CREATURE (%DAMAGE).",
|
||||||
"vcmi.battleWindow.damageEstimation.meleeKills" : "Атакувати %CREATURE (%DAMAGE, %KILLS).",
|
"vcmi.battleWindow.damageEstimation.meleeKills" : "Атакувати %CREATURE (%DAMAGE, %KILLS).",
|
||||||
"vcmi.battleWindow.damageEstimation.ranged" : "Стріляти в %CREATURE (%SHOTS, %DAMAGE).",
|
"vcmi.battleWindow.damageEstimation.ranged" : "Стріляти в %CREATURE (%SHOTS, %DAMAGE).",
|
||||||
@ -112,11 +144,12 @@
|
|||||||
"vcmi.battleWindow.damageEstimation.kills" : "%d загинуть",
|
"vcmi.battleWindow.damageEstimation.kills" : "%d загинуть",
|
||||||
"vcmi.battleWindow.damageEstimation.kills.1" : "%d загине",
|
"vcmi.battleWindow.damageEstimation.kills.1" : "%d загине",
|
||||||
|
|
||||||
|
"vcmi.battleResultsWindow.applyResultsLabel" : "Прийняти результат бою",
|
||||||
|
|
||||||
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover" : "Показувати доступних істот",
|
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.hover" : "Показувати доступних істот",
|
||||||
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.help" : "{Показувати доступних істот}\n\n Показує істот, яких можна придбати, замість їхнього приросту у зведенні по місту (нижній лівий кут).",
|
"vcmi.otherOptions.availableCreaturesAsDwellingLabel.help" : "{Показувати доступних істот}\n\n Показує істот, яких можна придбати, замість їхнього приросту у зведенні по місту (нижній лівий кут).",
|
||||||
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover" : "Показувати приріст істот",
|
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.hover" : "Показувати приріст істот",
|
||||||
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.help" : "{Показувати приріст істот}\n\n Показує щотижневий приріст істот, замість кількості яку можна придбати у зведенні по місту (нижній лівий кут).",
|
"vcmi.otherOptions.creatureGrowthAsDwellingLabel.help" : "{Показувати приріст істот}\n\n Показує щотижневий приріст істот, замість кількості яку можна придбати у зведенні по місту (нижній лівий кут).",
|
||||||
|
|
||||||
"vcmi.otherOptions.compactTownCreatureInfo.hover": "Компактне відображення істот у місті",
|
"vcmi.otherOptions.compactTownCreatureInfo.hover": "Компактне відображення істот у місті",
|
||||||
"vcmi.otherOptions.compactTownCreatureInfo.help": "{Компактне відображення істот у місті}\n\n Показує інформацію про істот у місті у зведенні по місту у більш компактному вигляді.",
|
"vcmi.otherOptions.compactTownCreatureInfo.help": "{Компактне відображення істот у місті}\n\n Показує інформацію про істот у місті у зведенні по місту у більш компактному вигляді.",
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ set(client_SRCS
|
|||||||
widgets/CArtifactsOfHeroMarket.cpp
|
widgets/CArtifactsOfHeroMarket.cpp
|
||||||
widgets/CArtifactsOfHeroBackpack.cpp
|
widgets/CArtifactsOfHeroBackpack.cpp
|
||||||
widgets/CWindowWithArtifacts.cpp
|
widgets/CWindowWithArtifacts.cpp
|
||||||
|
widgets/RadialMenu.cpp
|
||||||
|
|
||||||
windows/CCastleInterface.cpp
|
windows/CCastleInterface.cpp
|
||||||
windows/CCreatureWindow.cpp
|
windows/CCreatureWindow.cpp
|
||||||
@ -262,6 +263,7 @@ set(client_HEADERS
|
|||||||
widgets/CArtifactsOfHeroMarket.h
|
widgets/CArtifactsOfHeroMarket.h
|
||||||
widgets/CArtifactsOfHeroBackpack.h
|
widgets/CArtifactsOfHeroBackpack.h
|
||||||
widgets/CWindowWithArtifacts.h
|
widgets/CWindowWithArtifacts.h
|
||||||
|
widgets/RadialMenu.h
|
||||||
|
|
||||||
windows/CCastleInterface.h
|
windows/CCastleInterface.h
|
||||||
windows/CCreatureWindow.h
|
windows/CCreatureWindow.h
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "windows/CQuestLog.h"
|
#include "windows/CQuestLog.h"
|
||||||
#include "windows/CPuzzleWindow.h"
|
#include "windows/CPuzzleWindow.h"
|
||||||
#include "widgets/CComponent.h"
|
#include "widgets/CComponent.h"
|
||||||
|
#include "widgets/CGarrisonInt.h"
|
||||||
#include "widgets/Buttons.h"
|
#include "widgets/Buttons.h"
|
||||||
#include "windows/CTradeWindow.h"
|
#include "windows/CTradeWindow.h"
|
||||||
#include "windows/CSpellWindow.h"
|
#include "windows/CSpellWindow.h"
|
||||||
@ -536,8 +537,8 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
|
|||||||
if(castleInt)
|
if(castleInt)
|
||||||
{
|
{
|
||||||
castleInt->garr->selectSlot(nullptr);
|
castleInt->garr->selectSlot(nullptr);
|
||||||
castleInt->garr->setArmy(town->getUpperArmy(), 0);
|
castleInt->garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
||||||
castleInt->garr->setArmy(town->visitingHero, 1);
|
castleInt->garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
|
||||||
castleInt->garr->recreateSlots();
|
castleInt->garr->recreateSlots();
|
||||||
castleInt->heroes->update();
|
castleInt->heroes->update();
|
||||||
|
|
||||||
@ -601,7 +602,7 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
|
|||||||
adventureInt->onTownChanged(town);
|
adventureInt->onTownChanged(town);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cgh : GH.windows().findWindows<CGarrisonHolder>())
|
for (auto cgh : GH.windows().findWindows<IGarrisonHolder>())
|
||||||
cgh->updateGarrisons();
|
cgh->updateGarrisons();
|
||||||
|
|
||||||
for (auto cmw : GH.windows().findWindows<CTradeWindow>())
|
for (auto cmw : GH.windows().findWindows<CTradeWindow>())
|
||||||
|
@ -30,14 +30,14 @@ void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motio
|
|||||||
Point newPosition(motion.x, motion.y);
|
Point newPosition(motion.x, motion.y);
|
||||||
Point distance(-motion.xrel, -motion.yrel);
|
Point distance(-motion.xrel, -motion.yrel);
|
||||||
|
|
||||||
|
mouseButtonsMask = motion.state;
|
||||||
|
|
||||||
if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE))
|
if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE))
|
||||||
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
|
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
|
||||||
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_LEFT))
|
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_LEFT))
|
||||||
GH.events().dispatchMouseDragged(newPosition, distance);
|
GH.events().dispatchMouseDragged(newPosition, distance);
|
||||||
else
|
else
|
||||||
GH.input().setCursorPosition(newPosition);
|
GH.input().setCursorPosition(newPosition);
|
||||||
|
|
||||||
mouseButtonsMask = motion.state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
|
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)
|
||||||
|
@ -143,6 +143,12 @@ protected:
|
|||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IGarrisonHolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void updateGarrisons() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class IStatusBar
|
class IStatusBar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -243,34 +243,42 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
|
|||||||
|
|
||||||
for(auto it : copied)
|
for(auto it : copied)
|
||||||
{
|
{
|
||||||
if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE))
|
if (!vstd::contains(panningInterested, it))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!it->isGesturing() && it->receiveEvent(initialPosition, AEventsReceiver::GESTURE))
|
||||||
{
|
{
|
||||||
it->gesture(true, initialPosition, initialPosition);
|
|
||||||
it->panningState = true;
|
it->panningState = true;
|
||||||
|
it->gesture(true, initialPosition, initialPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
|
void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
|
||||||
{
|
{
|
||||||
|
dispatchGesturePanningStarted(initialPosition);
|
||||||
auto copied = panningInterested;
|
auto copied = panningInterested;
|
||||||
|
|
||||||
for(auto it : copied)
|
for(auto it : copied)
|
||||||
{
|
{
|
||||||
if (it->isGesturing())
|
if (it->isGesturing())
|
||||||
{
|
{
|
||||||
it->gesture(false, initialPosition, finalPosition);
|
|
||||||
it->panningState = false;
|
it->panningState = false;
|
||||||
|
it->gesture(false, initialPosition, finalPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
||||||
{
|
{
|
||||||
|
dispatchGesturePanningStarted(initialPosition);
|
||||||
auto copied = panningInterested;
|
auto copied = panningInterested;
|
||||||
|
|
||||||
for(auto it : copied)
|
for(auto it : copied)
|
||||||
{
|
{
|
||||||
|
if (!vstd::contains(panningInterested, it))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (it->isGesturing())
|
if (it->isGesturing())
|
||||||
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
|
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
|
||||||
}
|
}
|
||||||
@ -303,16 +311,16 @@ void EventDispatcher::dispatchMouseMoved(const Point & distance, const Point & p
|
|||||||
{
|
{
|
||||||
if (elem->isHovered())
|
if (elem->isHovered())
|
||||||
{
|
{
|
||||||
elem->hover(false);
|
|
||||||
elem->hoveredState = false;
|
elem->hoveredState = false;
|
||||||
|
elem->hover(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto & elem : newlyHovered)
|
for(auto & elem : newlyHovered)
|
||||||
{
|
{
|
||||||
elem->hover(true);
|
|
||||||
elem->hoveredState = true;
|
elem->hoveredState = true;
|
||||||
|
elem->hover(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//sending active, MotionInterested objects mouseMoved() call
|
//sending active, MotionInterested objects mouseMoved() call
|
||||||
|
@ -37,11 +37,6 @@ bool AEventsReceiver::isActive() const
|
|||||||
return activeState;
|
return activeState;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AEventsReceiver::isMouseLeftButtonPressed() const
|
|
||||||
{
|
|
||||||
return mouseClickedState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AEventsReceiver::activateEvents(ui16 what)
|
void AEventsReceiver::activateEvents(ui16 what)
|
||||||
{
|
{
|
||||||
assert((what & GENERAL) || (activeState & GENERAL));
|
assert((what & GENERAL) || (activeState & GENERAL));
|
||||||
@ -62,4 +57,14 @@ void AEventsReceiver::deactivateEvents(ui16 what)
|
|||||||
what = activeState;
|
what = activeState;
|
||||||
}
|
}
|
||||||
GH.events().deactivateElement(this, what & activeState);
|
GH.events().deactivateElement(this, what & activeState);
|
||||||
|
|
||||||
|
if (!(activeState & GESTURE) && panningState)
|
||||||
|
panningState = false;
|
||||||
|
|
||||||
|
if (!(activeState & LCLICK) && mouseClickedState)
|
||||||
|
mouseClickedState = false;
|
||||||
|
|
||||||
|
// FIXME: might lead to regressions, recheck before enabling
|
||||||
|
// if (!(activeState & HOVER))
|
||||||
|
// hoveredState = false;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,4 @@ public:
|
|||||||
|
|
||||||
/// Returns true if element is currently active and may receive events
|
/// Returns true if element is currently active and may receive events
|
||||||
bool isActive() const;
|
bool isActive() const;
|
||||||
|
|
||||||
/// Returns true if left mouse button was pressed when inside this element
|
|
||||||
bool isMouseLeftButtonPressed() const;
|
|
||||||
};
|
};
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
|
|
||||||
#include "Buttons.h"
|
#include "Buttons.h"
|
||||||
#include "TextControls.h"
|
#include "TextControls.h"
|
||||||
|
#include "RadialMenu.h"
|
||||||
|
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
|
#include "../render/IImage.h"
|
||||||
#include "../windows/CCreatureWindow.h"
|
#include "../windows/CCreatureWindow.h"
|
||||||
#include "../windows/GUIClasses.h"
|
#include "../windows/GUIClasses.h"
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
@ -25,6 +27,7 @@
|
|||||||
#include "../../lib/ArtifactUtils.h"
|
#include "../../lib/ArtifactUtils.h"
|
||||||
#include "../../lib/CGeneralTextHandler.h"
|
#include "../../lib/CGeneralTextHandler.h"
|
||||||
#include "../../lib/CCreatureHandler.h"
|
#include "../../lib/CCreatureHandler.h"
|
||||||
|
#include "../../lib/CConfigHandler.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
#include "../../lib/TextOperations.h"
|
#include "../../lib/TextOperations.h"
|
||||||
#include "../../lib/gameState/CGameState.h"
|
#include "../../lib/gameState/CGameState.h"
|
||||||
@ -72,16 +75,16 @@ void CGarrisonSlot::hover (bool on)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const bool isHeroOnMap = owner->armedObjs[0] // Hero is not a visitor and not a garrison defender
|
const bool isHeroOnMap = owner->upperArmy() // Hero is not a visitor and not a garrison defender
|
||||||
&& owner->armedObjs[0]->ID == Obj::HERO
|
&& owner->upperArmy()->ID == Obj::HERO
|
||||||
&& (!owner->armedObjs[1] || owner->armedObjs[1]->ID == Obj::HERO) // one hero or we are in the Heroes exchange window
|
&& (!owner->lowerArmy() || owner->lowerArmy()->ID == Obj::HERO) // one hero or we are in the Heroes exchange window
|
||||||
&& !(static_cast<const CGHeroInstance*>(owner->armedObjs[0]))->inTownGarrison;
|
&& !(static_cast<const CGHeroInstance*>(owner->upperArmy()))->inTownGarrison;
|
||||||
|
|
||||||
if(isHeroOnMap)
|
if(isHeroOnMap)
|
||||||
{
|
{
|
||||||
temp = CGI->generaltexth->allTexts[481]; //Select %s
|
temp = CGI->generaltexth->allTexts[481]; //Select %s
|
||||||
}
|
}
|
||||||
else if(upg == EGarrisonType::UP)
|
else if(upg == EGarrisonType::UPPER)
|
||||||
{
|
{
|
||||||
temp = CGI->generaltexth->tcommands[12]; //Select %s (in garrison)
|
temp = CGI->generaltexth->tcommands[12]; //Select %s (in garrison)
|
||||||
}
|
}
|
||||||
@ -125,16 +128,14 @@ void CGarrisonSlot::hover (bool on)
|
|||||||
|
|
||||||
const CArmedInstance * CGarrisonSlot::getObj() const
|
const CArmedInstance * CGarrisonSlot::getObj() const
|
||||||
{
|
{
|
||||||
return owner->armedObjs[upg];
|
return owner->army(upg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @return Whether the unit in the slot belongs to the current player.
|
|
||||||
bool CGarrisonSlot::our() const
|
bool CGarrisonSlot::our() const
|
||||||
{
|
{
|
||||||
return owner->owned[upg];
|
return owner->isArmyOwned(upg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @return Whether the unit in the slot belongs to an ally but not to the current player.
|
|
||||||
bool CGarrisonSlot::ally() const
|
bool CGarrisonSlot::ally() const
|
||||||
{
|
{
|
||||||
if(!getObj())
|
if(!getObj())
|
||||||
@ -227,8 +228,6 @@ bool CGarrisonSlot::highlightOrDropArtifact()
|
|||||||
bool CGarrisonSlot::split()
|
bool CGarrisonSlot::split()
|
||||||
{
|
{
|
||||||
const CGarrisonSlot * selection = owner->getSelection();
|
const CGarrisonSlot * selection = owner->getSelection();
|
||||||
owner->p2 = ID; // store the second stack pos
|
|
||||||
owner->pb = upg; // store the second stack owner (up or down army)
|
|
||||||
owner->setSplittingMode(false);
|
owner->setSplittingMode(false);
|
||||||
|
|
||||||
int minLeft=0, minRight=0;
|
int minLeft=0, minRight=0;
|
||||||
@ -252,17 +251,15 @@ bool CGarrisonSlot::split()
|
|||||||
int countLeft = selection->myStack ? selection->myStack->count : 0;
|
int countLeft = selection->myStack ? selection->myStack->count : 0;
|
||||||
int countRight = myStack ? myStack->count : 0;
|
int countRight = myStack ? myStack->count : 0;
|
||||||
|
|
||||||
GH.windows().createAndPushWindow<CSplitWindow>(selection->creature, std::bind(&CGarrisonInt::splitStacks, owner, _1, _2),
|
auto splitFunctor = [this, selection](int amountLeft, int amountRight)
|
||||||
minLeft, minRight, countLeft, countRight);
|
{
|
||||||
|
owner->splitStacks(selection, owner->army(upg), ID, amountRight);
|
||||||
|
};
|
||||||
|
|
||||||
|
GH.windows().createAndPushWindow<CSplitWindow>(selection->creature, splitFunctor, minLeft, minRight, countLeft, countRight);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If certain creates cannot be moved, the selection should change
|
|
||||||
/// Force reselection in these cases
|
|
||||||
/// * When attempting to take creatures from ally
|
|
||||||
/// * When attempting to swap creatures with an ally
|
|
||||||
/// * When attempting to take unremovable units
|
|
||||||
/// @return Whether reselection must be done
|
|
||||||
bool CGarrisonSlot::mustForceReselection() const
|
bool CGarrisonSlot::mustForceReselection() const
|
||||||
{
|
{
|
||||||
const CGarrisonSlot * selection = owner->getSelection();
|
const CGarrisonSlot * selection = owner->getSelection();
|
||||||
@ -277,10 +274,10 @@ bool CGarrisonSlot::mustForceReselection() const
|
|||||||
return true;
|
return true;
|
||||||
if (!owner->removableUnits)
|
if (!owner->removableUnits)
|
||||||
{
|
{
|
||||||
if (selection->upg == EGarrisonType::UP)
|
if (selection->upg == EGarrisonType::UPPER)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return creature || upg == EGarrisonType::UP;
|
return creature || upg == EGarrisonType::UPPER;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -318,7 +315,7 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const CArmedInstance * selectedObj = owner->armedObjs[selection->upg];
|
const CArmedInstance * selectedObj = owner->army(selection->upg);
|
||||||
bool lastHeroStackSelected = false;
|
bool lastHeroStackSelected = false;
|
||||||
if(selectedObj->stacksCount() == 1
|
if(selectedObj->stacksCount() == 1
|
||||||
&& owner->getSelection()->upg != upg
|
&& owner->getSelection()->upg != upg
|
||||||
@ -333,13 +330,13 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition)
|
|||||||
refr = split();
|
refr = split();
|
||||||
}
|
}
|
||||||
else if(!creature && lastHeroStackSelected) // split all except last creature
|
else if(!creature && lastHeroStackSelected) // split all except last creature
|
||||||
LOCPLINT->cb->splitStack(selectedObj, owner->armedObjs[upg], selection->ID, ID, selection->myStack->count - 1);
|
LOCPLINT->cb->splitStack(selectedObj, owner->army(upg), selection->ID, ID, selection->myStack->count - 1);
|
||||||
else if(creature != selection->creature) // swap
|
else if(creature != selection->creature) // swap
|
||||||
LOCPLINT->cb->swapCreatures(owner->armedObjs[upg], selectedObj, ID, selection->ID);
|
LOCPLINT->cb->swapCreatures(owner->army(upg), selectedObj, ID, selection->ID);
|
||||||
else if(lastHeroStackSelected) // merge last stack to other hero stack
|
else if(lastHeroStackSelected) // merge last stack to other hero stack
|
||||||
refr = split();
|
refr = split();
|
||||||
else // merge
|
else // merge
|
||||||
LOCPLINT->cb->mergeStacks(selectedObj, owner->armedObjs[upg], selection->ID, ID);
|
LOCPLINT->cb->mergeStacks(selectedObj, owner->army(upg), selection->ID, ID);
|
||||||
}
|
}
|
||||||
if(refr)
|
if(refr)
|
||||||
{
|
{
|
||||||
@ -349,17 +346,49 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
|
||||||
|
{
|
||||||
|
if(!on)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!myStack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!settings["input"]["radialWheelGarrisonSwipe"].Bool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto * otherArmy = upg == EGarrisonType::UPPER ? owner->lowerArmy() : owner->upperArmy();
|
||||||
|
|
||||||
|
bool stackExists = myStack != nullptr;
|
||||||
|
bool hasSameUnit = stackExists && !owner->army(upg)->getCreatureSlots(myStack->type, ID).empty();
|
||||||
|
bool hasOwnEmptySlots = stackExists && owner->army(upg)->getFreeSlot() != SlotID();
|
||||||
|
bool exchangeMode = stackExists && owner->upperArmy() && owner->lowerArmy();
|
||||||
|
bool hasOtherEmptySlots = exchangeMode && otherArmy->getFreeSlot() != SlotID();
|
||||||
|
bool hasAnyEmptySlots = hasOtherEmptySlots || hasOwnEmptySlots;
|
||||||
|
|
||||||
|
std::vector<RadialMenuConfig> menuElements = {
|
||||||
|
{ RadialMenuConfig::ITEM_NW, hasSameUnit, "stackMerge", "vcmi.radialWheel.mergeSameUnit", [this](){owner->bulkMergeStacks(this);} },
|
||||||
|
{ RadialMenuConfig::ITEM_NE, stackExists, "stackInfo", "vcmi.radialWheel.showUnitInformation", [this](){viewInfo();} },
|
||||||
|
{ RadialMenuConfig::ITEM_WW, hasOwnEmptySlots, "stackSplitOne", "vcmi.radialWheel.splitSingleUnit", [this](){splitIntoParts(this->getGarrison(), 1); } },
|
||||||
|
{ RadialMenuConfig::ITEM_EE, hasOwnEmptySlots, "stackSplitEqual", "vcmi.radialWheel.splitUnitEqually", [this](){owner->bulkSmartSplitStack(this);} },
|
||||||
|
{ RadialMenuConfig::ITEM_SW, hasOtherEmptySlots, "heroMove", "vcmi.radialWheel.moveUnit", [this](){owner->moveStackToAnotherArmy(this);} },
|
||||||
|
{ RadialMenuConfig::ITEM_SE, hasAnyEmptySlots, "heroSwap", "vcmi.radialWheel.splitUnit", [this](){ owner->selectSlot(this); owner->splitClick();} },
|
||||||
|
};
|
||||||
|
|
||||||
|
GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements);
|
||||||
|
}
|
||||||
|
|
||||||
void CGarrisonSlot::update()
|
void CGarrisonSlot::update()
|
||||||
{
|
{
|
||||||
if(getObj() != nullptr)
|
if(getObj() != nullptr)
|
||||||
{
|
{
|
||||||
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
|
addUsedEvents(LCLICK | SHOW_POPUP | GESTURE | HOVER);
|
||||||
myStack = getObj()->getStackPtr(ID);
|
myStack = getObj()->getStackPtr(ID);
|
||||||
creature = myStack ? myStack->type : nullptr;
|
creature = myStack ? myStack->type : nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
removeUsedEvents(LCLICK | SHOW_POPUP | HOVER);
|
removeUsedEvents(LCLICK | SHOW_POPUP | GESTURE | HOVER);
|
||||||
myStack = nullptr;
|
myStack = nullptr;
|
||||||
creature = nullptr;
|
creature = nullptr;
|
||||||
}
|
}
|
||||||
@ -379,7 +408,7 @@ void CGarrisonSlot::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * creature_)
|
CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, EGarrisonType Upg, const CStackInstance * creature_)
|
||||||
: ID(IID),
|
: ID(IID),
|
||||||
owner(Owner),
|
owner(Owner),
|
||||||
myStack(creature_),
|
myStack(creature_),
|
||||||
@ -427,16 +456,14 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGa
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGarrisonSlot::splitIntoParts(CGarrisonSlot::EGarrisonType type, int amount)
|
void CGarrisonSlot::splitIntoParts(EGarrisonType type, int amount)
|
||||||
{
|
{
|
||||||
auto empty = owner->getEmptySlot(type);
|
auto empty = owner->getEmptySlot(type);
|
||||||
|
|
||||||
if(empty == SlotID())
|
if(empty == SlotID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
owner->pb = type;
|
owner->splitStacks(this, owner->army(type), empty, amount);
|
||||||
owner->p2 = empty;
|
|
||||||
owner->splitStacks(1, amount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGarrisonSlot::handleSplittingShortcuts()
|
bool CGarrisonSlot::handleSplittingShortcuts()
|
||||||
@ -500,21 +527,23 @@ void CGarrisonInt::addSplitBtn(std::shared_ptr<CButton> button)
|
|||||||
void CGarrisonInt::createSlots()
|
void CGarrisonInt::createSlots()
|
||||||
{
|
{
|
||||||
int distance = interx + (smallIcons ? 32 : 58);
|
int distance = interx + (smallIcons ? 32 : 58);
|
||||||
for(int i = 0; i < 2; i++)
|
for(auto i : { EGarrisonType::UPPER, EGarrisonType::LOWER })
|
||||||
{
|
{
|
||||||
|
Point offset = garOffset * static_cast<int>(i);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots;
|
std::vector<std::shared_ptr<CGarrisonSlot>> garrisonSlots;
|
||||||
garrisonSlots.resize(7);
|
garrisonSlots.resize(7);
|
||||||
if(armedObjs[i])
|
if(army(i))
|
||||||
{
|
{
|
||||||
for(auto & elem : armedObjs[i]->Slots())
|
for(auto & elem : army(i)->Slots())
|
||||||
{
|
{
|
||||||
garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (elem.first.getNum()*distance), i*garOffset.y, elem.first, static_cast<CGarrisonSlot::EGarrisonType>(i), elem.second);
|
garrisonSlots[elem.first.getNum()] = std::make_shared<CGarrisonSlot>(this, offset.x + (elem.first.getNum()*distance), offset.y, elem.first, i, elem.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int j = 0; j < 7; j++)
|
for(int j = 0; j < 7; j++)
|
||||||
{
|
{
|
||||||
if(!garrisonSlots[j])
|
if(!garrisonSlots[j])
|
||||||
garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, i*garOffset.x + (j*distance), i*garOffset.y, SlotID(j), static_cast<CGarrisonSlot::EGarrisonType>(i), nullptr);
|
garrisonSlots[j] = std::make_shared<CGarrisonSlot>(this, offset.x + (j*distance), offset.y, SlotID(j), i, nullptr);
|
||||||
|
|
||||||
if(layout == ESlotsLayout::TWO_ROWS && j >= 4)
|
if(layout == ESlotsLayout::TWO_ROWS && j >= 4)
|
||||||
{
|
{
|
||||||
@ -555,9 +584,10 @@ void CGarrisonInt::splitClick()
|
|||||||
setSplittingMode(!getSplittingMode());
|
setSplittingMode(!getSplittingMode());
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
void CGarrisonInt::splitStacks(int, int amountRight)
|
|
||||||
|
void CGarrisonInt::splitStacks(const CGarrisonSlot * from, const CArmedInstance * armyDest, SlotID slotDest, int amount )
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->splitStack(armedObjs[getSelection()->upg], armedObjs[pb], getSelection()->ID, p2, amountRight);
|
LOCPLINT->cb->splitStack(armedObjs[from->upg], armyDest, from->ID, slotDest, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGarrisonInt::checkSelected(const CGarrisonSlot * selected, TQuantity min) const
|
bool CGarrisonInt::checkSelected(const CGarrisonSlot * selected, TQuantity min) const
|
||||||
@ -571,9 +601,9 @@ void CGarrisonInt::moveStackToAnotherArmy(const CGarrisonSlot * selected)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const auto srcArmyType = selected->upg;
|
const auto srcArmyType = selected->upg;
|
||||||
const auto destArmyType = srcArmyType == CGarrisonSlot::UP
|
const auto destArmyType = srcArmyType == EGarrisonType::UPPER
|
||||||
? CGarrisonSlot::DOWN
|
? EGarrisonType::LOWER
|
||||||
: CGarrisonSlot::UP;
|
: EGarrisonType::UPPER;
|
||||||
|
|
||||||
auto srcArmy = armedObjs[srcArmyType];
|
auto srcArmy = armedObjs[srcArmyType];
|
||||||
auto destArmy = armedObjs[destArmyType];
|
auto destArmy = armedObjs[destArmyType];
|
||||||
@ -615,9 +645,9 @@ void CGarrisonInt::bulkMoveArmy(const CGarrisonSlot * selected)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const auto srcArmyType = selected->upg;
|
const auto srcArmyType = selected->upg;
|
||||||
const auto destArmyType = (srcArmyType == CGarrisonSlot::UP)
|
const auto destArmyType = (srcArmyType == EGarrisonType::UPPER)
|
||||||
? CGarrisonSlot::DOWN
|
? EGarrisonType::LOWER
|
||||||
: CGarrisonSlot::UP;
|
: EGarrisonType::UPPER;
|
||||||
|
|
||||||
auto srcArmy = armedObjs[srcArmyType];
|
auto srcArmy = armedObjs[srcArmyType];
|
||||||
auto destArmy = armedObjs[destArmyType];
|
auto destArmy = armedObjs[destArmyType];
|
||||||
@ -669,24 +699,20 @@ void CGarrisonInt::bulkSmartSplitStack(const CGarrisonSlot * selected)
|
|||||||
LOCPLINT->cb->bulkSmartSplitStack(armedObjs[type]->id, selected->ID);
|
LOCPLINT->cb->bulkSmartSplitStack(armedObjs[type]->id, selected->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset,
|
CGarrisonInt::CGarrisonInt(const Point & position, int inx, const Point & garsOffset, const CArmedInstance * s1, const CArmedInstance * s2, bool _removableUnits, bool smallImgs, ESlotsLayout _layout)
|
||||||
const CArmedInstance * s1, const CArmedInstance * s2,
|
: highlighted(nullptr)
|
||||||
bool _removableUnits, bool smallImgs, ESlotsLayout _layout)
|
, inSplittingMode(false)
|
||||||
: highlighted(nullptr),
|
, interx(inx)
|
||||||
inSplittingMode(false),
|
, garOffset(garsOffset)
|
||||||
interx(inx),
|
, smallIcons(smallImgs)
|
||||||
garOffset(garsOffset),
|
, removableUnits(_removableUnits)
|
||||||
pb(false),
|
, layout(_layout)
|
||||||
smallIcons(smallImgs),
|
|
||||||
removableUnits(_removableUnits),
|
|
||||||
layout(_layout)
|
|
||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
setArmy(s1, false);
|
setArmy(s1, EGarrisonType::UPPER);
|
||||||
setArmy(s2, true);
|
setArmy(s2, EGarrisonType::LOWER);
|
||||||
pos.x += x;
|
pos += position;
|
||||||
pos.y += y;
|
|
||||||
createSlots();
|
createSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,19 +757,51 @@ bool CGarrisonInt::getSplittingMode()
|
|||||||
return inSplittingMode;
|
return inSplittingMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotID CGarrisonInt::getEmptySlot(CGarrisonSlot::EGarrisonType type) const
|
SlotID CGarrisonInt::getEmptySlot(EGarrisonType type) const
|
||||||
{
|
{
|
||||||
assert(armedObjs[type]);
|
assert(army(type));
|
||||||
return armedObjs[type] ? armedObjs[type]->getFreeSlot() : SlotID();
|
return army(type) ? army(type)->getFreeSlot() : SlotID();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGarrisonInt::hasEmptySlot(CGarrisonSlot::EGarrisonType type) const
|
bool CGarrisonInt::hasEmptySlot(EGarrisonType type) const
|
||||||
{
|
{
|
||||||
return getEmptySlot(type) != SlotID();
|
return getEmptySlot(type) != SlotID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGarrisonInt::setArmy(const CArmedInstance * army, bool bottomGarrison)
|
const CArmedInstance * CGarrisonInt::upperArmy() const
|
||||||
{
|
{
|
||||||
owned[bottomGarrison] = army ? (army->tempOwner == LOCPLINT->playerID || army->tempOwner == PlayerColor::UNFLAGGABLE) : false;
|
return army(EGarrisonType::UPPER);
|
||||||
armedObjs[bottomGarrison] = army;
|
}
|
||||||
|
|
||||||
|
const CArmedInstance * CGarrisonInt::lowerArmy() const
|
||||||
|
{
|
||||||
|
return army(EGarrisonType::LOWER);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CArmedInstance * CGarrisonInt::army(EGarrisonType which) const
|
||||||
|
{
|
||||||
|
if(armedObjs.count(which))
|
||||||
|
return armedObjs.at(which);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGarrisonInt::isArmyOwned(EGarrisonType which) const
|
||||||
|
{
|
||||||
|
const auto * object = army(which);
|
||||||
|
|
||||||
|
if (!object)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (object->tempOwner == LOCPLINT->playerID)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (object->tempOwner == PlayerColor::UNFLAGGABLE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGarrisonInt::setArmy(const CArmedInstance * army, EGarrisonType type)
|
||||||
|
{
|
||||||
|
armedObjs[type] = army;
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../windows/CWindowObject.h"
|
#include "../gui/CIntObject.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class CArmedInstance;
|
class CArmedInstance;
|
||||||
class CCreatureSet;
|
|
||||||
class CStackInstance;
|
class CStackInstance;
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
@ -22,9 +21,14 @@ VCMI_LIB_NAMESPACE_END
|
|||||||
class CGarrisonInt;
|
class CGarrisonInt;
|
||||||
class CButton;
|
class CButton;
|
||||||
class CAnimImage;
|
class CAnimImage;
|
||||||
class CGarrisonSlot;
|
|
||||||
class CLabel;
|
class CLabel;
|
||||||
|
|
||||||
|
enum class EGarrisonType
|
||||||
|
{
|
||||||
|
UPPER, /// up garrison (Garrisoned)
|
||||||
|
LOWER, /// down garrison (Visiting)
|
||||||
|
};
|
||||||
|
|
||||||
/// A single garrison slot which holds one creature of a specific amount
|
/// A single garrison slot which holds one creature of a specific amount
|
||||||
class CGarrisonSlot : public CIntObject
|
class CGarrisonSlot : public CIntObject
|
||||||
{
|
{
|
||||||
@ -32,36 +36,42 @@ class CGarrisonSlot : public CIntObject
|
|||||||
CGarrisonInt *owner;
|
CGarrisonInt *owner;
|
||||||
const CStackInstance * myStack; //nullptr if slot is empty
|
const CStackInstance * myStack; //nullptr if slot is empty
|
||||||
const CCreature * creature;
|
const CCreature * creature;
|
||||||
|
EGarrisonType upg;
|
||||||
/// Type of Garrison for slot (up or down)
|
|
||||||
enum EGarrisonType
|
|
||||||
{
|
|
||||||
UP=0, ///< 0 - up garrison (Garrisoned)
|
|
||||||
DOWN, ///< 1 - down garrison (Visiting)
|
|
||||||
} upg; ///< Flag indicating if it is the up or down garrison
|
|
||||||
|
|
||||||
std::shared_ptr<CAnimImage> creatureImage;
|
std::shared_ptr<CAnimImage> creatureImage;
|
||||||
std::shared_ptr<CAnimImage> selectionImage; // image for selection, not always visible
|
std::shared_ptr<CAnimImage> selectionImage; // image for selection, not always visible
|
||||||
std::shared_ptr<CLabel> stackCount;
|
std::shared_ptr<CLabel> stackCount;
|
||||||
|
|
||||||
|
public:
|
||||||
bool viewInfo();
|
bool viewInfo();
|
||||||
bool highlightOrDropArtifact();
|
bool highlightOrDropArtifact();
|
||||||
bool split();
|
bool split();
|
||||||
|
|
||||||
|
/// If certain creates cannot be moved, the selection should change
|
||||||
|
/// Force reselection in these cases
|
||||||
|
/// * When attempting to take creatures from ally
|
||||||
|
/// * When attempting to swap creatures with an ally
|
||||||
|
/// * When attempting to take unremovable units
|
||||||
|
/// @return Whether reselection must be done
|
||||||
bool mustForceReselection() const;
|
bool mustForceReselection() const;
|
||||||
|
|
||||||
void setHighlight(bool on);
|
void setHighlight(bool on);
|
||||||
std::function<void()> getDismiss() const;
|
std::function<void()> getDismiss() const;
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void hover (bool on) override; //call-in
|
|
||||||
const CArmedInstance * getObj() const;
|
const CArmedInstance * getObj() const;
|
||||||
bool our() const;
|
bool our() const;
|
||||||
SlotID getSlot() const { return ID; }
|
SlotID getSlot() const { return ID; }
|
||||||
|
EGarrisonType getGarrison() const { return upg; }
|
||||||
bool ally() const;
|
bool ally() const;
|
||||||
|
|
||||||
|
// CIntObject overrides
|
||||||
void showPopupWindow(const Point & cursorPosition) override;
|
void showPopupWindow(const Point & cursorPosition) override;
|
||||||
void clickPressed(const Point & cursorPosition) override;
|
void clickPressed(const Point & cursorPosition) override;
|
||||||
|
void hover (bool on) override; //call-in
|
||||||
|
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * creature_ = nullptr);
|
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg, const CStackInstance * creature_);
|
||||||
|
|
||||||
void splitIntoParts(EGarrisonType type, int amount);
|
void splitIntoParts(EGarrisonType type, int amount);
|
||||||
bool handleSplittingShortcuts(); /// Returns true when some shortcut is pressed, false otherwise
|
bool handleSplittingShortcuts(); /// Returns true when some shortcut is pressed, false otherwise
|
||||||
@ -80,6 +90,8 @@ class CGarrisonInt :public CIntObject
|
|||||||
void createSlots();
|
void createSlots();
|
||||||
bool checkSelected(const CGarrisonSlot * selected, TQuantity min = 0) const;
|
bool checkSelected(const CGarrisonSlot * selected, TQuantity min = 0) const;
|
||||||
|
|
||||||
|
std::map<EGarrisonType, const CArmedInstance*> armedObjs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class ESlotsLayout
|
enum class ESlotsLayout
|
||||||
{
|
{
|
||||||
@ -92,11 +104,8 @@ public:
|
|||||||
Point garOffset; ///< Offset between garrisons (not used if only one hero)
|
Point garOffset; ///< Offset between garrisons (not used if only one hero)
|
||||||
std::vector<std::shared_ptr<CButton>> splitButtons; ///< May be empty if no buttons
|
std::vector<std::shared_ptr<CButton>> splitButtons; ///< May be empty if no buttons
|
||||||
|
|
||||||
SlotID p2; ///< TODO: comment me
|
bool smallIcons; ///< true - 32x32 imgs, false - 58x64
|
||||||
bool pb,
|
bool removableUnits; ///< player Can remove units from up
|
||||||
smallIcons, ///< true - 32x32 imgs, false - 58x64
|
|
||||||
removableUnits, ///< player Can remove units from up
|
|
||||||
owned[2]; ///< player Owns up or down army ([0] upper, [1] lower)
|
|
||||||
|
|
||||||
ESlotsLayout layout;
|
ESlotsLayout layout;
|
||||||
|
|
||||||
@ -106,18 +115,21 @@ public:
|
|||||||
void setSplittingMode(bool on);
|
void setSplittingMode(bool on);
|
||||||
bool getSplittingMode();
|
bool getSplittingMode();
|
||||||
|
|
||||||
bool hasEmptySlot(CGarrisonSlot::EGarrisonType type) const;
|
bool hasEmptySlot(EGarrisonType type) const;
|
||||||
SlotID getEmptySlot(CGarrisonSlot::EGarrisonType type) const;
|
SlotID getEmptySlot(EGarrisonType type) const;
|
||||||
|
|
||||||
const CArmedInstance * armedObjs[2]; ///< [0] is upper, [1] is down
|
void setArmy(const CArmedInstance * army, EGarrisonType type);
|
||||||
|
|
||||||
void setArmy(const CArmedInstance * army, bool bottomGarrison);
|
|
||||||
void addSplitBtn(std::shared_ptr<CButton> button);
|
void addSplitBtn(std::shared_ptr<CButton> button);
|
||||||
|
|
||||||
void recreateSlots();
|
void recreateSlots();
|
||||||
|
|
||||||
|
const CArmedInstance* upperArmy() const;
|
||||||
|
const CArmedInstance* lowerArmy() const;
|
||||||
|
const CArmedInstance* army(EGarrisonType which) const;
|
||||||
|
bool isArmyOwned(EGarrisonType which) const;
|
||||||
|
|
||||||
void splitClick(); ///< handles click on split button
|
void splitClick(); ///< handles click on split button
|
||||||
void splitStacks(int amountLeft, int amountRight); ///< TODO: comment me
|
void splitStacks(const CGarrisonSlot * from, const CArmedInstance * armyDest, SlotID slotDest, int amount); ///< TODO: comment me
|
||||||
void moveStackToAnotherArmy(const CGarrisonSlot * selected);
|
void moveStackToAnotherArmy(const CGarrisonSlot * selected);
|
||||||
void bulkMoveArmy(const CGarrisonSlot * selected);
|
void bulkMoveArmy(const CGarrisonSlot * selected);
|
||||||
void bulkMergeStacks(const CGarrisonSlot * selected); // Gather all creatures of selected type to the selected slot from other hero/garrison slots
|
void bulkMergeStacks(const CGarrisonSlot * selected); // Gather all creatures of selected type to the selected slot from other hero/garrison slots
|
||||||
@ -125,24 +137,17 @@ public:
|
|||||||
void bulkSmartSplitStack(const CGarrisonSlot * selected);
|
void bulkSmartSplitStack(const CGarrisonSlot * selected);
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param x, y Position
|
/// @param position Relative position to parent element
|
||||||
/// @param inx Distance between slots;
|
/// @param slotInterval Distance between slots;
|
||||||
/// @param garsOffset
|
/// @param secondGarrisonOffset
|
||||||
/// @param s1, s2 Top and bottom armies
|
/// @param s1, s2 Top and bottom armies
|
||||||
/// @param _removableUnits You can take units from top
|
/// @param _removableUnits You can take units from top
|
||||||
/// @param smallImgs Units images size 64x58 or 32x32
|
/// @param smallImgs Units images size 64x58 or 32x32
|
||||||
/// @param _layout - when TWO_ROWS - Display slots in 2 rows (1st row = 4 slots, 2nd = 3 slots), REVERSED_TWO_ROWS = 3 slots in 1st row
|
/// @param _layout - when TWO_ROWS - Display slots in 2 rows (1st row = 4 slots, 2nd = 3 slots), REVERSED_TWO_ROWS = 3 slots in 1st row
|
||||||
CGarrisonInt(int x, int y, int inx,
|
CGarrisonInt(const Point & position, int slotInterval,
|
||||||
const Point & garsOffset,
|
const Point & secondGarrisonOffset,
|
||||||
const CArmedInstance * s1, const CArmedInstance * s2 = nullptr,
|
const CArmedInstance * upperArmy, const CArmedInstance * lowerArmy = nullptr,
|
||||||
bool _removableUnits = true,
|
bool _removableUnits = true,
|
||||||
bool smallImgs = false,
|
bool smallImgs = false,
|
||||||
ESlotsLayout _layout = ESlotsLayout::ONE_ROW);
|
ESlotsLayout _layout = ESlotsLayout::ONE_ROW);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CGarrisonHolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void updateGarrisons() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero):
|
|||||||
}
|
}
|
||||||
|
|
||||||
CInteractableHeroTooltip::CInteractableHeroTooltip(Point pos, const CGHeroInstance * hero):
|
CInteractableHeroTooltip::CInteractableHeroTooltip(Point pos, const CGHeroInstance * hero):
|
||||||
CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), hero, nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
|
CGarrisonInt(pos + Point(0, 73), 4, Point(0, 0), hero, nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
|
||||||
{
|
{
|
||||||
init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
|
init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CInteractableTownTooltip::CInteractableTownTooltip(Point pos, const CGTownInstance * town)
|
CInteractableTownTooltip::CInteractableTownTooltip(Point pos, const CGTownInstance * town)
|
||||||
: CGarrisonInt(pos.x, pos.y+73, 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
|
: CGarrisonInt(pos + Point(0, 73), 4, Point(0, 0), town->getUpperArmy(), nullptr, true, true, CGarrisonInt::ESlotsLayout::REVERSED_TWO_ROWS)
|
||||||
{
|
{
|
||||||
init(InfoAboutTown(town, true));
|
init(InfoAboutTown(town, true));
|
||||||
}
|
}
|
||||||
|
141
client/widgets/RadialMenu.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* RadialMenu.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "RadialMenu.h"
|
||||||
|
|
||||||
|
#include "Images.h"
|
||||||
|
#include "TextControls.h"
|
||||||
|
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/WindowHandler.h"
|
||||||
|
#include "../render/IImage.h"
|
||||||
|
#include "../CGameInfo.h"
|
||||||
|
|
||||||
|
#include "../../lib/CGeneralTextHandler.h"
|
||||||
|
|
||||||
|
RadialMenuItem::RadialMenuItem(const std::string & imageName, const std::string & hoverText, const std::function<void()> & callback)
|
||||||
|
: callback(callback)
|
||||||
|
, hoverText(hoverText)
|
||||||
|
{
|
||||||
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
|
|
||||||
|
inactiveImage = std::make_shared<CPicture>("radialMenu/itemInactive", Point(0, 0));
|
||||||
|
selectedImage = std::make_shared<CPicture>("radialMenu/itemEmpty", Point(0, 0));
|
||||||
|
|
||||||
|
iconImage = std::make_shared<CPicture>("radialMenu/" + imageName, Point(0, 0));
|
||||||
|
|
||||||
|
pos = selectedImage->pos;
|
||||||
|
selectedImage->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialMenuItem::setSelected(bool selected)
|
||||||
|
{
|
||||||
|
selectedImage->setEnabled(selected);
|
||||||
|
inactiveImage->setEnabled(!selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig):
|
||||||
|
centerPosition(positionToCenter)
|
||||||
|
{
|
||||||
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
|
pos += positionToCenter;
|
||||||
|
|
||||||
|
Point itemSize = Point(70, 80);
|
||||||
|
moveBy(-itemSize / 2);
|
||||||
|
pos.w = itemSize.x;
|
||||||
|
pos.h = itemSize.y;
|
||||||
|
|
||||||
|
for (auto const & item : menuConfig)
|
||||||
|
addItem(item.itemPosition, item.enabled, item.imageName, item.hoverText, item.callback);
|
||||||
|
|
||||||
|
statusBar = CGStatusBar::create(-80, -100, "radialMenu/statusBar");
|
||||||
|
|
||||||
|
for(const auto & item : items)
|
||||||
|
pos = pos.include(item->pos);
|
||||||
|
|
||||||
|
fitToScreen(10);
|
||||||
|
|
||||||
|
addUsedEvents(GESTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialMenu::addItem(const Point & offset, bool enabled, const std::string & path, const std::string & hoverText, const std::function<void()>& callback )
|
||||||
|
{
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto item = std::make_shared<RadialMenuItem>(path, CGI->generaltexth->translate(hoverText), callback);
|
||||||
|
|
||||||
|
item->moveBy(offset);
|
||||||
|
|
||||||
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RadialMenuItem> RadialMenu::findNearestItem(const Point & cursorPosition) const
|
||||||
|
{
|
||||||
|
static const int requiredDistanceFromCenter = 45;
|
||||||
|
|
||||||
|
// cursor is inside centeral area -> no selection
|
||||||
|
if ((centerPosition - cursorPosition).length() < requiredDistanceFromCenter)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int bestDistance = std::numeric_limits<int>::max();
|
||||||
|
std::shared_ptr<RadialMenuItem> bestItem;
|
||||||
|
|
||||||
|
for(const auto & item : items)
|
||||||
|
{
|
||||||
|
Point vector = item->pos.center() - cursorPosition;
|
||||||
|
|
||||||
|
if (vector.length() < bestDistance)
|
||||||
|
{
|
||||||
|
bestDistance = vector.length();
|
||||||
|
bestItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(bestItem);
|
||||||
|
return bestItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialMenu::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
||||||
|
{
|
||||||
|
auto newSelection = findNearestItem(currentPosition);
|
||||||
|
|
||||||
|
|
||||||
|
if (newSelection != selectedItem)
|
||||||
|
{
|
||||||
|
if (selectedItem)
|
||||||
|
selectedItem->setSelected(false);
|
||||||
|
|
||||||
|
if (newSelection)
|
||||||
|
{
|
||||||
|
GH.statusbar()->write(newSelection->hoverText);
|
||||||
|
newSelection->setSelected(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GH.statusbar()->clear();
|
||||||
|
|
||||||
|
selectedItem = newSelection;
|
||||||
|
|
||||||
|
GH.windows().totalRedraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
|
||||||
|
{
|
||||||
|
if (on)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto item = findNearestItem(finalPosition);
|
||||||
|
|
||||||
|
// we need to close this window first so if action spawns a new window it won't be closed instead
|
||||||
|
GH.windows().popWindows(1);
|
||||||
|
if (item)
|
||||||
|
item->callback();
|
||||||
|
}
|
68
client/widgets/RadialMenu.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* RadialMenu.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../gui/CIntObject.h"
|
||||||
|
|
||||||
|
class IImage;
|
||||||
|
|
||||||
|
class CGarrisonInt;
|
||||||
|
class CGarrisonSlot;
|
||||||
|
class CGStatusBar;
|
||||||
|
|
||||||
|
struct RadialMenuConfig
|
||||||
|
{
|
||||||
|
static constexpr Point ITEM_NW = Point(-40, -70);
|
||||||
|
static constexpr Point ITEM_NE = Point(+40, -70);
|
||||||
|
static constexpr Point ITEM_WW = Point(-80, 0);
|
||||||
|
static constexpr Point ITEM_EE = Point(+80, 0);
|
||||||
|
static constexpr Point ITEM_SW = Point(-40, +70);
|
||||||
|
static constexpr Point ITEM_SE = Point(+40, +70);
|
||||||
|
|
||||||
|
Point itemPosition;
|
||||||
|
bool enabled;
|
||||||
|
std::string imageName;
|
||||||
|
std::string hoverText;
|
||||||
|
std::function<void()> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RadialMenuItem : public CIntObject
|
||||||
|
{
|
||||||
|
friend class RadialMenu;
|
||||||
|
|
||||||
|
std::shared_ptr<CPicture> iconImage;
|
||||||
|
std::shared_ptr<CPicture> selectedImage;
|
||||||
|
std::shared_ptr<CPicture> inactiveImage;
|
||||||
|
std::function<void()> callback;
|
||||||
|
std::string hoverText;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RadialMenuItem(const std::string & imageName, const std::string & hoverText, const std::function<void()> & callback);
|
||||||
|
|
||||||
|
void setSelected(bool selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
class RadialMenu : public CIntObject
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<RadialMenuItem>> items;
|
||||||
|
std::shared_ptr<CGStatusBar> statusBar;
|
||||||
|
std::shared_ptr<RadialMenuItem> selectedItem;
|
||||||
|
|
||||||
|
Point centerPosition;
|
||||||
|
|
||||||
|
void addItem(const Point & offset, bool enabled, const std::string & path, const std::string & hoverText, const std::function<void()> & callback);
|
||||||
|
|
||||||
|
std::shared_ptr<RadialMenuItem> findNearestItem(const Point & cursorPosition) const;
|
||||||
|
public:
|
||||||
|
RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig);
|
||||||
|
|
||||||
|
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
|
||||||
|
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
||||||
|
};
|
@ -25,6 +25,7 @@
|
|||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
#include "../widgets/MiscWidgets.h"
|
#include "../widgets/MiscWidgets.h"
|
||||||
#include "../widgets/CComponent.h"
|
#include "../widgets/CComponent.h"
|
||||||
|
#include "../widgets/CGarrisonInt.h"
|
||||||
#include "../widgets/Buttons.h"
|
#include "../widgets/Buttons.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
#include "../render/Canvas.h"
|
#include "../render/Canvas.h"
|
||||||
@ -1154,7 +1155,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
|
|||||||
center();
|
center();
|
||||||
updateShadow();
|
updateShadow();
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(305, 387, 4, Point(0,96), town->getUpperArmy(), town->visitingHero);
|
garr = std::make_shared<CGarrisonInt>(Point(305, 387), 4, Point(0,96), town->getUpperArmy(), town->visitingHero);
|
||||||
garr->setRedrawParent(true);
|
garr->setRedrawParent(true);
|
||||||
|
|
||||||
heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
|
heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CGarrisonInt.h"
|
#include "../windows/CWindowObject.h"
|
||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
@ -212,7 +212,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Class which manages the castle window
|
/// Class which manages the castle window
|
||||||
class CCastleInterface : public CStatusbarWindow, public CGarrisonHolder
|
class CCastleInterface : public CStatusbarWindow, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
std::shared_ptr<CLabel> title;
|
std::shared_ptr<CLabel> title;
|
||||||
std::shared_ptr<CLabel> income;
|
std::shared_ptr<CLabel> income;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
#include "../widgets/MiscWidgets.h"
|
#include "../widgets/MiscWidgets.h"
|
||||||
#include "../widgets/CComponent.h"
|
#include "../widgets/CComponent.h"
|
||||||
|
#include "../widgets/CGarrisonInt.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
#include "../widgets/Buttons.h"
|
#include "../widgets/Buttons.h"
|
||||||
#include "../render/CAnimation.h"
|
#include "../render/CAnimation.h"
|
||||||
@ -200,7 +201,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
|
|||||||
std::string helpBox = heroscrn[32];
|
std::string helpBox = heroscrn[32];
|
||||||
boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]);
|
boost::algorithm::replace_first(helpBox, "%s", CGI->generaltexth->allTexts[43]);
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(15, 485, 8, Point(), curHero);
|
garr = std::make_shared<CGarrisonInt>(Point(15, 485), 8, Point(), curHero);
|
||||||
auto split = std::make_shared<CButton>(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); });
|
auto split = std::make_shared<CButton>(Point(539, 519), "hsbtns9.def", CButton::tooltip(CGI->generaltexth->allTexts[256], helpBox), [&](){ garr->splitClick(); });
|
||||||
garr->addSplitBtn(split);
|
garr->addSplitBtn(split);
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vcmi/FactionMember.h>
|
|
||||||
|
|
||||||
#include "../../lib/bonuses/Bonus.h"
|
|
||||||
#include "../../lib/bonuses/IBonusBearer.h"
|
|
||||||
#include "../widgets/CWindowWithArtifacts.h"
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
#include "../widgets/CGarrisonInt.h"
|
#include "CWindowObject.h"
|
||||||
|
|
||||||
|
#include "../../lib/bonuses/IBonusBearer.h"
|
||||||
|
|
||||||
|
#include <vcmi/FactionMember.h>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -33,6 +33,7 @@ class CToggleButton;
|
|||||||
class CToggleGroup;
|
class CToggleGroup;
|
||||||
class CGStatusBar;
|
class CGStatusBar;
|
||||||
class CTextBox;
|
class CTextBox;
|
||||||
|
class CGarrisonInt;
|
||||||
|
|
||||||
/// Button which switches hero selection
|
/// Button which switches hero selection
|
||||||
class CHeroSwitcher : public CIntObject
|
class CHeroSwitcher : public CIntObject
|
||||||
@ -46,7 +47,7 @@ public:
|
|||||||
CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_);
|
CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHeroWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts
|
class CHeroWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts
|
||||||
{
|
{
|
||||||
std::shared_ptr<CLabel> name;
|
std::shared_ptr<CLabel> name;
|
||||||
std::shared_ptr<CLabel> title;
|
std::shared_ptr<CLabel> title;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/Shortcut.h"
|
#include "../gui/Shortcut.h"
|
||||||
#include "../widgets/CComponent.h"
|
#include "../widgets/CComponent.h"
|
||||||
|
#include "../widgets/CGarrisonInt.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
#include "../widgets/MiscWidgets.h"
|
#include "../widgets/MiscWidgets.h"
|
||||||
#include "../widgets/Buttons.h"
|
#include "../widgets/Buttons.h"
|
||||||
@ -646,7 +647,7 @@ void CKingdomInterface::heroRemoved()
|
|||||||
|
|
||||||
void CKingdomInterface::updateGarrisons()
|
void CKingdomInterface::updateGarrisons()
|
||||||
{
|
{
|
||||||
if(auto garrison = std::dynamic_pointer_cast<CGarrisonHolder>(tabArea->getItem()))
|
if(auto garrison = std::dynamic_pointer_cast<IGarrisonHolder>(tabArea->getItem()))
|
||||||
garrison->updateGarrisons();
|
garrison->updateGarrisons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +693,7 @@ void CKingdHeroList::updateGarrisons()
|
|||||||
{
|
{
|
||||||
for(std::shared_ptr<CIntObject> object : heroes->getItems())
|
for(std::shared_ptr<CIntObject> object : heroes->getItems())
|
||||||
{
|
{
|
||||||
if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get()))
|
if(IGarrisonHolder * garrison = dynamic_cast<IGarrisonHolder*>(object.get()))
|
||||||
garrison->updateGarrisons();
|
garrison->updateGarrisons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,7 +745,7 @@ void CKingdTownList::updateGarrisons()
|
|||||||
{
|
{
|
||||||
for(std::shared_ptr<CIntObject> object : towns->getItems())
|
for(std::shared_ptr<CIntObject> object : towns->getItems())
|
||||||
{
|
{
|
||||||
if(CGarrisonHolder * garrison = dynamic_cast<CGarrisonHolder*>(object.get()))
|
if(IGarrisonHolder * garrison = dynamic_cast<IGarrisonHolder*>(object.get()))
|
||||||
garrison->updateGarrisons();
|
garrison->updateGarrisons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -772,7 +773,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
|||||||
hall = std::make_shared<CTownInfo>( 69, 31, town, true);
|
hall = std::make_shared<CTownInfo>( 69, 31, town, true);
|
||||||
fort = std::make_shared<CTownInfo>(111, 31, town, false);
|
fort = std::make_shared<CTownInfo>(111, 31, town, false);
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(313, 3, 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
|
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
|
||||||
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
|
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
|
||||||
|
|
||||||
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->builded >= CGI->settings()->getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
|
||||||
@ -790,8 +791,8 @@ CTownItem::CTownItem(const CGTownInstance * Town)
|
|||||||
void CTownItem::updateGarrisons()
|
void CTownItem::updateGarrisons()
|
||||||
{
|
{
|
||||||
garr->selectSlot(nullptr);
|
garr->selectSlot(nullptr);
|
||||||
garr->setArmy(town->getUpperArmy(), 0);
|
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
||||||
garr->setArmy(town->visitingHero, 1);
|
garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
|
||||||
garr->recreateSlots();
|
garr->recreateSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,7 +914,7 @@ CHeroItem::CHeroItem(const CGHeroInstance * Hero)
|
|||||||
artButtons->addCallback(std::bind(&CHeroItem::onArtChange, this, _1));
|
artButtons->addCallback(std::bind(&CHeroItem::onArtChange, this, _1));
|
||||||
artButtons->setSelected(0);
|
artButtons->setSelected(0);
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(6, 78, 4, Point(), hero, nullptr, true, true);
|
garr = std::make_shared<CGarrisonInt>(Point(6, 78), 4, Point(), hero, nullptr, true, true);
|
||||||
|
|
||||||
portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait, 0, 5, 6);
|
portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait, 0, 5, 6);
|
||||||
heroArea = std::make_shared<CHeroArea>(5, 6, hero);
|
heroArea = std::make_shared<CHeroArea>(5, 6, hero);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CWindowWithArtifacts.h"
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
#include "../widgets/CGarrisonInt.h"
|
#include "CWindowObject.h"
|
||||||
|
|
||||||
class CButton;
|
class CButton;
|
||||||
class CAnimImage;
|
class CAnimImage;
|
||||||
@ -27,6 +27,7 @@ class MoraleLuckBox;
|
|||||||
class CListBox;
|
class CListBox;
|
||||||
class CTabbedInt;
|
class CTabbedInt;
|
||||||
class CGStatusBar;
|
class CGStatusBar;
|
||||||
|
class CGarrisonInt;
|
||||||
|
|
||||||
class CKingdHeroList;
|
class CKingdHeroList;
|
||||||
class CKingdTownList;
|
class CKingdTownList;
|
||||||
@ -195,7 +196,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Class which holds all parts of kingdom overview window
|
/// Class which holds all parts of kingdom overview window
|
||||||
class CKingdomInterface : public CWindowObject, public CGarrisonHolder, public CArtifactHolder
|
class CKingdomInterface : public CWindowObject, public IGarrisonHolder, public CArtifactHolder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct OwnedObjectInfo
|
struct OwnedObjectInfo
|
||||||
@ -255,7 +256,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// List item with town
|
/// List item with town
|
||||||
class CTownItem : public CIntObject, public CGarrisonHolder
|
class CTownItem : public CIntObject, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
std::shared_ptr<CAnimImage> background;
|
std::shared_ptr<CAnimImage> background;
|
||||||
std::shared_ptr<CAnimImage> picture;
|
std::shared_ptr<CAnimImage> picture;
|
||||||
@ -282,7 +283,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// List item with hero
|
/// List item with hero
|
||||||
class CHeroItem : public CIntObject, public CGarrisonHolder
|
class CHeroItem : public CIntObject, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
const CGHeroInstance * hero;
|
const CGHeroInstance * hero;
|
||||||
|
|
||||||
@ -315,7 +316,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Tab with all hero-specific data
|
/// Tab with all hero-specific data
|
||||||
class CKingdHeroList : public CIntObject, public CGarrisonHolder, public CWindowWithArtifacts
|
class CKingdHeroList : public CIntObject, public IGarrisonHolder, public CWindowWithArtifacts
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<CListBox> heroes;
|
std::shared_ptr<CListBox> heroes;
|
||||||
@ -331,7 +332,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Tab with all town-specific data
|
/// Tab with all town-specific data
|
||||||
class CKingdTownList : public CIntObject, public CGarrisonHolder
|
class CKingdTownList : public CIntObject, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<CListBox> towns;
|
std::shared_ptr<CListBox> towns;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
|
|
||||||
#include "../widgets/CComponent.h"
|
#include "../widgets/CComponent.h"
|
||||||
|
#include "../widgets/CGarrisonInt.h"
|
||||||
#include "../widgets/MiscWidgets.h"
|
#include "../widgets/MiscWidgets.h"
|
||||||
#include "../widgets/CreatureCostBox.h"
|
#include "../widgets/CreatureCostBox.h"
|
||||||
#include "../widgets/Buttons.h"
|
#include "../widgets/Buttons.h"
|
||||||
@ -968,7 +969,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
|
|||||||
|
|
||||||
//garrison interface
|
//garrison interface
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(69, qeLayout ? 122 : 131, 4, Point(418,0), heroInst[0], heroInst[1], true, true);
|
garr = std::make_shared<CGarrisonInt>(Point(69, qeLayout ? 122 : 131), 4, Point(418,0), heroInst[0], heroInst[1], true, true);
|
||||||
auto splitButtonCallback = [&](){ garr->splitClick(); };
|
auto splitButtonCallback = [&](){ garr->splitClick(); };
|
||||||
garr->addSplitBtn(std::make_shared<CButton>( Point( 10, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback));
|
garr->addSplitBtn(std::make_shared<CButton>( Point( 10, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback));
|
||||||
garr->addSplitBtn(std::make_shared<CButton>( Point(744, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback));
|
garr->addSplitBtn(std::make_shared<CButton>( Point(744, qeLayout ? 122 : 132), "TSBTNS.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3]), splitButtonCallback));
|
||||||
@ -1351,7 +1352,7 @@ CGarrisonWindow::CGarrisonWindow(const CArmedInstance * up, const CGHeroInstance
|
|||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(92, 127, 4, Point(0,96), up, down, removableUnits);
|
garr = std::make_shared<CGarrisonInt>(Point(92, 127), 4, Point(0,96), up, down, removableUnits);
|
||||||
{
|
{
|
||||||
auto split = std::make_shared<CButton>(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } );
|
auto split = std::make_shared<CButton>(Point(88, 314), "IDV6432.DEF", CButton::tooltip(CGI->generaltexth->tcommands[3], ""), [&](){ garr->splitClick(); } );
|
||||||
garr->addSplitBtn(split);
|
garr->addSplitBtn(split);
|
||||||
@ -1424,7 +1425,7 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectI
|
|||||||
quit = std::make_shared<CButton>(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), EShortcut::GLOBAL_ACCEPT);
|
quit = std::make_shared<CButton>(Point(294, 275), "IOKAY.DEF", CButton::tooltip(), std::bind(&CHillFortWindow::close, this), EShortcut::GLOBAL_ACCEPT);
|
||||||
statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||||
|
|
||||||
garr = std::make_shared<CGarrisonInt>(108, 60, 18, Point(), hero, nullptr);
|
garr = std::make_shared<CGarrisonInt>(Point(108, 60), 18, Point(), hero, nullptr);
|
||||||
updateGarrisons();
|
updateGarrisons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "../lib/ResourceSet.h"
|
#include "../lib/ResourceSet.h"
|
||||||
#include "../lib/int3.h"
|
#include "../lib/int3.h"
|
||||||
#include "../widgets/CWindowWithArtifacts.h"
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
#include "../widgets/CGarrisonInt.h"
|
|
||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
@ -38,6 +37,8 @@ class CToggleButton;
|
|||||||
class CGStatusBar;
|
class CGStatusBar;
|
||||||
class CTextBox;
|
class CTextBox;
|
||||||
class CResDataBar;
|
class CResDataBar;
|
||||||
|
class CGarrisonInt;
|
||||||
|
class CGarrisonSlot;
|
||||||
|
|
||||||
enum class EUserEvent;
|
enum class EUserEvent;
|
||||||
|
|
||||||
@ -273,7 +274,7 @@ private:
|
|||||||
void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
|
void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CExchangeWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts
|
class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts
|
||||||
{
|
{
|
||||||
std::array<std::shared_ptr<CLabel>, 2> titles;
|
std::array<std::shared_ptr<CLabel>, 2> titles;
|
||||||
std::vector<std::shared_ptr<CAnimImage>> primSkillImages;//shared for both heroes
|
std::vector<std::shared_ptr<CAnimImage>> primSkillImages;//shared for both heroes
|
||||||
@ -348,7 +349,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Creature transformer window
|
/// Creature transformer window
|
||||||
class CTransformerWindow : public CStatusbarWindow, public CGarrisonHolder
|
class CTransformerWindow : public CStatusbarWindow, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
class CItem : public CIntObject
|
class CItem : public CIntObject
|
||||||
{
|
{
|
||||||
@ -449,7 +450,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Garrison window where you can take creatures out of the hero to place it on the garrison
|
/// Garrison window where you can take creatures out of the hero to place it on the garrison
|
||||||
class CGarrisonWindow : public CWindowObject, public CGarrisonHolder
|
class CGarrisonWindow : public CWindowObject, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
std::shared_ptr<CLabel> title;
|
std::shared_ptr<CLabel> title;
|
||||||
std::shared_ptr<CAnimImage> banner;
|
std::shared_ptr<CAnimImage> banner;
|
||||||
@ -466,7 +467,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Hill fort is the building where you can upgrade units
|
/// Hill fort is the building where you can upgrade units
|
||||||
class CHillFortWindow : public CStatusbarWindow, public CGarrisonHolder
|
class CHillFortWindow : public CStatusbarWindow, public IGarrisonHolder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static const int slotsCount = 7;
|
static const int slotsCount = 7;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CGarrisonInt.h"
|
#include "../windows/CWindowObject.h"
|
||||||
|
|
||||||
class CButton;
|
class CButton;
|
||||||
class CreatureCostBox;
|
class CreatureCostBox;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"$schema" : "http://json-schema.org/draft-04/schema",
|
"$schema" : "http://json-schema.org/draft-04/schema",
|
||||||
"required" : [ "general", "video", "adventure", "battle", "server", "logging", "launcher", "gameTweaks" ],
|
"required" : [ "general", "video", "adventure", "battle", "input", "server", "logging", "launcher", "gameTweaks" ],
|
||||||
"definitions" : {
|
"definitions" : {
|
||||||
"logLevelEnum" : {
|
"logLevelEnum" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
@ -207,6 +207,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"input" : {
|
||||||
|
"type" : "object",
|
||||||
|
"additionalProperties" : false,
|
||||||
|
"default" : {},
|
||||||
|
"required" : [ "radialWheelGarrisonSwipe" ],
|
||||||
|
"properties" : {
|
||||||
|
"radialWheelGarrisonSwipe" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"default" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"adventure" : {
|
"adventure" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
|
@ -67,6 +67,11 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr Point operator-() const
|
||||||
|
{
|
||||||
|
return Point(-x, -y);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Point operator-(const T &b) const
|
constexpr Point operator-(const T &b) const
|
||||||
{
|
{
|
||||||
|