diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index 95e103563..57042cb81 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -350,14 +350,27 @@ void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point if (!on) return; + if (!myStack) + return; + + bool stackExists = myStack != nullptr; + bool hasSameUnit = stackExists && !owner->army(upg)->getCreatureSlots(myStack->type, ID).empty(); + bool hasEmptySlots = stackExists && owner->army(upg)->getFreeSlot() != SlotID(); + bool exchangeMode = stackExists && owner->upperArmy() && owner->lowerArmy(); + std::vector menuElements = { - { RadialMenuConfig::ITEM_NW, "stackMerge", "Merge same units", [this](){owner->bulkMergeStacks(this);} }, - { RadialMenuConfig::ITEM_NE, "stackInfo", "Show unit information", [this](){viewInfo();} }, - { RadialMenuConfig::ITEM_WW, "stackSplitOne", "Split off single unit", [this](){splitIntoParts(this->getGarrison(), 1); } }, - { RadialMenuConfig::ITEM_EE, "stackSplitEqual", "Split unit equally", [this](){owner->bulkSmartSplitStack(this);} }, - { RadialMenuConfig::ITEM_SW, "heroMove", "Move unit to another army", [this](){owner->moveStackToAnotherArmy(this);} }, + { RadialMenuConfig::ITEM_NW, hasSameUnit, "stackMerge", "Merge same units", [this](){owner->bulkMergeStacks(this);} }, + { RadialMenuConfig::ITEM_NE, stackExists, "stackInfo", "Show unit information", [this](){viewInfo();} }, + { RadialMenuConfig::ITEM_WW, hasEmptySlots, "stackSplitOne", "Split off single unit", [this](){splitIntoParts(this->getGarrison(), 1); } }, + { RadialMenuConfig::ITEM_EE, hasEmptySlots, "stackSplitEqual", "Split unit equally", [this](){owner->bulkSmartSplitStack(this);} }, + { RadialMenuConfig::ITEM_SW, exchangeMode, "heroMove", "Move unit to another army", [this](){owner->moveStackToAnotherArmy(this);} }, }; + // additional options to consider: + // - Ctrl + Shift + Click - splits from current stack, stacks of 1 in all free slots + // - Alt + Shift + Click - dismiss stack with confirmation window + // Split unit (same as button) + GH.windows().createAndPushWindow(pos.center(), menuElements); } diff --git a/client/widgets/RadialMenu.cpp b/client/widgets/RadialMenu.cpp index f0f056790..217e523ea 100644 --- a/client/widgets/RadialMenu.cpp +++ b/client/widgets/RadialMenu.cpp @@ -33,13 +33,13 @@ RadialMenu::RadialMenu(const Point & positionToCenter, const std::vectorpos.dimensions(); moveBy(-itemSize / 2); for (auto const & item : menuConfig) - addItem(item.itemPosition, item.imageName, item.hoverText, item.callback); + addItem(item.itemPosition, item.enabled, item.imageName, item.hoverText, item.callback); statusBar = CGStatusBar::create(-80, -100, "radialMenu/statusBar"); @@ -51,8 +51,11 @@ RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector& callback ) +void RadialMenu::addItem(const Point & offset, bool enabled, const std::string & path, const std::string & hoverText, const std::function& callback ) { + if (!enabled) + return; + auto item = std::make_shared(path, hoverText, callback); item->moveBy(offset); diff --git a/client/widgets/RadialMenu.h b/client/widgets/RadialMenu.h index a0e4c0977..f7ce5ad07 100644 --- a/client/widgets/RadialMenu.h +++ b/client/widgets/RadialMenu.h @@ -27,6 +27,7 @@ struct RadialMenuConfig static constexpr Point ITEM_SE = Point(+40, +70); Point itemPosition; + bool enabled; std::string imageName; std::string hoverText; std::function callback; @@ -51,7 +52,7 @@ class RadialMenu : public CIntObject std::shared_ptr statusBar; - void addItem(const Point & offset, const std::string & path, const std::string & hoverText, const std::function & callback); + void addItem(const Point & offset, bool enabled, const std::string & path, const std::string & hoverText, const std::function & callback); std::shared_ptr findNearestItem(const Point & cursorPosition) const; public: