1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

Fixed input event ordering. Fixes radial menu show/hide logic

This commit is contained in:
Ivan Savenko 2023-07-16 17:56:47 +03:00
parent d26595cef7
commit e3f5ab57f2
11 changed files with 67 additions and 75 deletions

View File

Before

Width:  |  Height:  |  Size: 824 B

After

Width:  |  Height:  |  Size: 824 B

View File

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View File

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

View File

@ -30,14 +30,14 @@ void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motio
Point newPosition(motion.x, motion.y);
Point distance(-motion.xrel, -motion.yrel);
mouseButtonsMask = motion.state;
if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_MIDDLE))
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_LEFT))
GH.events().dispatchMouseDragged(newPosition, distance);
else
GH.input().setCursorPosition(newPosition);
mouseButtonsMask = motion.state;
}
void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & button)

View File

@ -243,39 +243,41 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
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->gesture(true, initialPosition, initialPosition);
}
}
}
void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
{
dispatchGesturePanningStarted(initialPosition);
auto copied = panningInterested;
for(auto it : copied)
{
if (it->isGesturing())
{
it->gesture(false, initialPosition, finalPosition);
it->panningState = false;
it->gesture(false, initialPosition, finalPosition);
}
}
}
void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
dispatchGesturePanningStarted(initialPosition);
auto copied = panningInterested;
for(auto it : copied)
{
if (!it->isGesturing() && it->receiveEvent(initialPosition, AEventsReceiver::GESTURE))
{
it->gesture(true, initialPosition, initialPosition);
it->panningState = true;
}
if (!vstd::contains(panningInterested, it))
continue;
if (it->isGesturing())
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
@ -309,16 +311,16 @@ void EventDispatcher::dispatchMouseMoved(const Point & distance, const Point & p
{
if (elem->isHovered())
{
elem->hover(false);
elem->hoveredState = false;
elem->hover(false);
}
}
}
for(auto & elem : newlyHovered)
{
elem->hover(true);
elem->hoveredState = true;
elem->hover(true);
}
//sending active, MotionInterested objects mouseMoved() call

View File

@ -37,11 +37,6 @@ bool AEventsReceiver::isActive() const
return activeState;
}
bool AEventsReceiver::isMouseLeftButtonPressed() const
{
return mouseClickedState;
}
void AEventsReceiver::activateEvents(ui16 what)
{
assert((what & GENERAL) || (activeState & GENERAL));
@ -62,4 +57,14 @@ void AEventsReceiver::deactivateEvents(ui16 what)
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;
}

View File

@ -99,7 +99,4 @@ public:
/// Returns true if element is currently active and may receive events
bool isActive() const;
/// Returns true if left mouse button was pressed when inside this element
bool isMouseLeftButtonPressed() const;
};

View File

@ -347,8 +347,18 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition)
void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
if (on)
GH.windows().createAndPushWindow<RadialMenu>(pos.center(), owner, this);
if (!on)
return;
std::vector<RadialMenuConfig> menuElements = {
{ RadialMenuConfig::ITEM_NW, "stackMerge", "", [this](){owner->bulkMergeStacks(this);} },
{ RadialMenuConfig::ITEM_NE, "stackInfo", "", [this](){viewInfo();} },
{ RadialMenuConfig::ITEM_WW, "stackSplitOne", "", [this](){splitIntoParts(this->getGarrison(), 1); } },
{ RadialMenuConfig::ITEM_EE, "stackSplitEqual", "", [this](){owner->bulkSmartSplitStack(this);} },
{ RadialMenuConfig::ITEM_SW, "heroMove", "", [this](){owner->moveStackToAnotherArmy(this);} },
};
GH.windows().createAndPushWindow<RadialMenu>(pos.center(), menuElements);
}
void CGarrisonSlot::update()

View File

@ -16,10 +16,10 @@
#include "../gui/CGuiHandler.h"
#include "../gui/WindowHandler.h"
#include "../render/IImage.h"
#include "CGarrisonInt.h"
RadialMenuItem::RadialMenuItem(const std::string & imageName, const std::function<void()> & callback)
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;
@ -35,42 +35,20 @@ bool RadialMenuItem::isInside(const Point & position)
return !image->isTransparent(localPosition);
}
void RadialMenuItem::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
{
}
void RadialMenuItem::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
}
RadialMenu::RadialMenu(const Point & positionToCenter, CGarrisonInt * army, CGarrisonSlot * slot)
RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos += positionToCenter;
bool isExchange = army->upperArmy() && army->lowerArmy(); // two armies exist
addItem(Point(0,0), "stackEmpty", [](){});
addItem(Point(0,0), "itemEmpty", "", [](){});
Point itemSize = items.back()->pos.dimensions();
moveBy(-itemSize / 2);
addItem(ITEM_NW, "stackMerge", [=](){army->bulkMergeStacks(slot);});
addItem(ITEM_NE, "stackInfo", [=](){slot->viewInfo();});
for (auto const & item : menuConfig)
addItem(item.itemPosition, item.imageName, item.hoverText, item.callback);
addItem(ITEM_WW, "stackSplitOne", [=](){slot->splitIntoParts(slot->getGarrison(), 1); });
addItem(ITEM_EE, "stackSplitEqual", [=](){army->bulkSmartSplitStack(slot);});
if (isExchange)
{
addItem(ITEM_SW, "stackMove", [=](){army->moveStackToAnotherArmy(slot);});
//FIXME: addItem(ITEM_SE, "stackSplitDialog", [=](){slot->split();});
}
//statusBarBackground = std::make_shared<CFilledTexture>("DiBoxBck", Rect(-itemSize.x * 2, -100, itemSize.x * 4, 20));
//statusBar = CGStatusBar::create(statusBarBackground);
statusBar = CGStatusBar::create(-80, -100, "radialMenu/statusBar");
for(const auto & item : items)
pos = pos.include(item->pos);
@ -80,9 +58,9 @@ RadialMenu::RadialMenu(const Point & positionToCenter, CGarrisonInt * army, CGar
addUsedEvents(GESTURE);
}
void RadialMenu::addItem(const Point & offset, const std::string & path, const std::function<void()>& callback )
void RadialMenu::addItem(const Point & offset, const std::string & path, const std::string & hoverText, const std::function<void()>& callback )
{
auto item = std::make_shared<RadialMenuItem>(path, callback);
auto item = std::make_shared<RadialMenuItem>(path, hoverText, callback);
item->moveBy(offset);
@ -94,11 +72,6 @@ void RadialMenu::gesturePanning(const Point & initialPosition, const Point & cur
}
void RadialMenu::show(Canvas & to)
{
showAll(to);
}
void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
if (!on)

View File

@ -15,44 +15,49 @@ class IImage;
class CGarrisonInt;
class CGarrisonSlot;
class CFilledTexture;
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;
std::string imageName;
std::string hoverText;
std::function<void()> callback;
};
class RadialMenuItem : public CIntObject
{
friend class RadialMenu;
std::shared_ptr<IImage> image;
std::shared_ptr<CPicture> picture;
public:
std::function<void()> callback;
std::string hoverText;
RadialMenuItem(const std::string& imageName, const std::function<void()>& callback);
public:
RadialMenuItem(const std::string & imageName, const std::string & hoverText, const std::function<void()> & callback);
bool isInside(const Point & position);
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
};
class RadialMenu : public CIntObject
{
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);
std::vector<std::shared_ptr<RadialMenuItem>> items;
std::shared_ptr<CFilledTexture> statusBarBackground;
std::shared_ptr<CGStatusBar> statusBar;
void addItem(const Point & offset, const std::string & path, const std::function<void()>& callback );
void addItem(const Point & offset, const std::string & path, const std::string & hoverText, const std::function<void()> & callback);
public:
RadialMenu(const Point & positionToCenter, CGarrisonInt * army, CGarrisonSlot * slot);
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;
void show(Canvas & to) override;
};