1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +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 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)

View File

@@ -243,39 +243,41 @@ 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 (!it->isGesturing() && it->receiveEvent(initialPosition, AEventsReceiver::GESTURE)) if (!vstd::contains(panningInterested, it))
{ continue;
it->gesture(true, initialPosition, initialPosition);
it->panningState = true;
}
if (it->isGesturing()) if (it->isGesturing())
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance); it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
@@ -309,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

View File

@@ -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;
} }

View File

@@ -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;
}; };

View File

@@ -347,8 +347,18 @@ void CGarrisonSlot::clickPressed(const Point & cursorPosition)
void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point & finalPosition) void CGarrisonSlot::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{ {
if (on) if (!on)
GH.windows().createAndPushWindow<RadialMenu>(pos.center(), owner, this); 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() void CGarrisonSlot::update()

View File

@@ -16,10 +16,10 @@
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/WindowHandler.h" #include "../gui/WindowHandler.h"
#include "../render/IImage.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) : callback(callback)
, hoverText(hoverText)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
@@ -35,42 +35,20 @@ bool RadialMenuItem::isInside(const Point & position)
return !image->isTransparent(localPosition); return !image->isTransparent(localPosition);
} }
void RadialMenuItem::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig)
{
}
void RadialMenuItem::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
}
RadialMenu::RadialMenu(const Point & positionToCenter, CGarrisonInt * army, CGarrisonSlot * slot)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos += positionToCenter; pos += positionToCenter;
bool isExchange = army->upperArmy() && army->lowerArmy(); // two armies exist addItem(Point(0,0), "itemEmpty", "", [](){});
addItem(Point(0,0), "stackEmpty", [](){});
Point itemSize = items.back()->pos.dimensions(); Point itemSize = items.back()->pos.dimensions();
moveBy(-itemSize / 2); moveBy(-itemSize / 2);
addItem(ITEM_NW, "stackMerge", [=](){army->bulkMergeStacks(slot);}); for (auto const & item : menuConfig)
addItem(ITEM_NE, "stackInfo", [=](){slot->viewInfo();}); addItem(item.itemPosition, item.imageName, item.hoverText, item.callback);
addItem(ITEM_WW, "stackSplitOne", [=](){slot->splitIntoParts(slot->getGarrison(), 1); }); statusBar = CGStatusBar::create(-80, -100, "radialMenu/statusBar");
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);
for(const auto & item : items) for(const auto & item : items)
pos = pos.include(item->pos); pos = pos.include(item->pos);
@@ -80,9 +58,9 @@ RadialMenu::RadialMenu(const Point & positionToCenter, CGarrisonInt * army, CGar
addUsedEvents(GESTURE); 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); 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) void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{ {
if (!on) if (!on)

View File

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