Browse Source

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

Ivan Savenko 2 years ago
parent
commit
e3f5ab57f2

+ 0 - 0
Mods/vcmi/Data/radialMenu/stackMove.png → Mods/vcmi/Data/radialMenu/heroMove.png


+ 0 - 0
Mods/vcmi/Data/radialMenu/stackSwap.png → Mods/vcmi/Data/radialMenu/heroSwap.png


+ 0 - 0
Mods/vcmi/Data/radialMenu/stackEmpty.png → Mods/vcmi/Data/radialMenu/itemEmpty.png


BIN
Mods/vcmi/Data/radialMenu/statusBar.png


+ 2 - 2
client/eventsSDL/InputSourceMouse.cpp

@@ -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)

+ 12 - 10
client/gui/EventDispatcher.cpp

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

+ 10 - 5
client/gui/EventsReceiver.cpp

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

+ 0 - 3
client/gui/EventsReceiver.h

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

+ 12 - 2
client/widgets/CGarrisonInt.cpp

@@ -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()

+ 9 - 36
client/widgets/RadialMenu.cpp

@@ -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();});
-
-	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();});
-	}
+	for (auto const & item : menuConfig)
+		addItem(item.itemPosition, item.imageName, item.hoverText, item.callback);
 
-	//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)

+ 22 - 17
client/widgets/RadialMenu.h

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