diff --git a/client/adventureMap/CMinimap.cpp b/client/adventureMap/CMinimap.cpp index ed7af2f1f..57c740fcd 100644 --- a/client/adventureMap/CMinimap.cpp +++ b/client/adventureMap/CMinimap.cpp @@ -88,7 +88,7 @@ void CMinimapInstance::showAll(Canvas & to) } CMinimap::CMinimap(const Rect & position) - : CIntObject(LCLICK | SHOW_POPUP | HOVER | MOVE | GESTURE, position.topLeft()), + : CIntObject(LCLICK | SHOW_POPUP | DRAG | MOVE | GESTURE, position.topLeft()), level(0) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); @@ -162,10 +162,9 @@ void CMinimap::hover(bool on) GH.statusbar()->clear(); } -void CMinimap::mouseMoved(const Point & cursorPosition) +void CMinimap::mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) { - if(isMouseLeftButtonPressed()) - moveAdvMapSelection(cursorPosition); + moveAdvMapSelection(cursorPosition); } void CMinimap::showAll(Canvas & to) diff --git a/client/adventureMap/CMinimap.h b/client/adventureMap/CMinimap.h index 6829dc16b..496611bb5 100644 --- a/client/adventureMap/CMinimap.h +++ b/client/adventureMap/CMinimap.h @@ -46,8 +46,8 @@ class CMinimap : public CIntObject void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; void clickLeft(tribool down, bool previousState) override; void showPopupWindow() override; - void hover (bool on) override; - void mouseMoved (const Point & cursorPosition) override; + void hover(bool on) override; + void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override; /// relocates center of adventure map screen to currently hovered tile void moveAdvMapSelection(const Point & positionGlobal); diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index 4426e465d..f1e7cad03 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -197,7 +197,7 @@ void BattleFieldController::gesturePanning(const Point & initialPosition, const owner.actionsController->onHexHovered(getHoveredHex()); } -void BattleFieldController::mouseMoved(const Point & cursorPosition) +void BattleFieldController::mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) { hoveredHex = getHexAtPosition(cursorPosition); currentAttackOriginPoint = cursorPosition; diff --git a/client/battle/BattleFieldController.h b/client/battle/BattleFieldController.h index d1941fb68..76e6dbec6 100644 --- a/client/battle/BattleFieldController.h +++ b/client/battle/BattleFieldController.h @@ -90,7 +90,7 @@ class BattleFieldController : public CIntObject void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; - void mouseMoved(const Point & cursorPosition) override; + void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override; void clickLeft(tribool down, bool previousState) override; void showPopupWindow() override; void activate() override; diff --git a/client/eventsSDL/InputHandler.cpp b/client/eventsSDL/InputHandler.cpp index 6f9401d2b..999283d8c 100644 --- a/client/eventsSDL/InputHandler.cpp +++ b/client/eventsSDL/InputHandler.cpp @@ -75,7 +75,7 @@ void InputHandler::handleCurrentEvent(const SDL_Event & current) void InputHandler::processEvents() { boost::unique_lock lock(eventsMutex); - for (auto const & currentEvent : eventsQueue) + for(const auto & currentEvent : eventsQueue) handleCurrentEvent(currentEvent); eventsQueue.clear(); @@ -87,7 +87,7 @@ bool InputHandler::ignoreEventsUntilInput() bool inputFound = false; boost::unique_lock lock(eventsMutex); - for (auto const & event : eventsQueue) + for(const auto & event : eventsQueue) { switch(event.type) { @@ -226,7 +226,7 @@ void InputHandler::moveCursorPosition(const Point & distance) void InputHandler::setCursorPosition(const Point & position) { cursorPosition = position; - GH.events().dispatchMouseMoved(position); + GH.events().dispatchMouseMoved(Point(0, 0), position); } void InputHandler::startTextInput(const Rect & where) diff --git a/client/eventsSDL/InputSourceMouse.cpp b/client/eventsSDL/InputSourceMouse.cpp index dae4344c6..3a1c98f49 100644 --- a/client/eventsSDL/InputSourceMouse.cpp +++ b/client/eventsSDL/InputSourceMouse.cpp @@ -26,6 +26,8 @@ void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motio 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); diff --git a/client/eventsSDL/UserEventHandler.cpp b/client/eventsSDL/UserEventHandler.cpp index 25c78eafa..b24528a6d 100644 --- a/client/eventsSDL/UserEventHandler.cpp +++ b/client/eventsSDL/UserEventHandler.cpp @@ -82,7 +82,7 @@ void UserEventHandler::handleUserEvent(const SDL_UserEvent & user) break; } case EUserEvent::FAKE_MOUSE_MOVE: - GH.events().dispatchMouseMoved(GH.getCursorPosition()); + GH.events().dispatchMouseMoved(Point(0, 0), GH.getCursorPosition()); break; default: logGlobal->error("Unknown user event. Code %d", user.code); diff --git a/client/gui/EventDispatcher.cpp b/client/gui/EventDispatcher.cpp index 8e491a925..6c1fe9070 100644 --- a/client/gui/EventDispatcher.cpp +++ b/client/gui/EventDispatcher.cpp @@ -31,6 +31,7 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb) processList(AEventsReceiver::SHOW_POPUP, rclickable); processList(AEventsReceiver::HOVER, hoverable); processList(AEventsReceiver::MOVE, motioninterested); + processList(AEventsReceiver::DRAG, draginterested); processList(AEventsReceiver::KEYBOARD, keyinterested); processList(AEventsReceiver::TIME, timeinterested); processList(AEventsReceiver::WHEEL, wheelInterested); @@ -63,7 +64,7 @@ void EventDispatcher::dispatchTimer(uint32_t msPassed) for (auto & elem : hlp) { if(!vstd::contains(timeinterested,elem)) continue; - (elem)->tick(msPassed); + elem->tick(msPassed); } } @@ -270,7 +271,7 @@ void EventDispatcher::dispatchGesturePinch(const Point & initialPosition, double } } -void EventDispatcher::dispatchMouseMoved(const Point & position) +void EventDispatcher::dispatchMouseMoved(const Point & distance, const Point & position) { EventReceiversList newlyHovered; @@ -288,8 +289,8 @@ void EventDispatcher::dispatchMouseMoved(const Point & position) { if (elem->isHovered()) { - (elem)->hover(false); - (elem)->hoveredState = false; + elem->hover(false); + elem->hoveredState = false; } } } @@ -305,8 +306,16 @@ void EventDispatcher::dispatchMouseMoved(const Point & position) for(auto & elem : miCopy) { if(elem->receiveEvent(position, AEventsReceiver::HOVER)) - { - (elem)->mouseMoved(position); - } + elem->mouseMoved(position, distance); + } +} + +void EventDispatcher::dispatchMouseDragged(const Point & currentPosition, const Point & lastUpdateDistance) +{ + EventReceiversList diCopy = draginterested; + for(auto & elem : diCopy) + { + if (elem->mouseClickedState) + elem->mouseDragged(currentPosition, lastUpdateDistance); } } diff --git a/client/gui/EventDispatcher.h b/client/gui/EventDispatcher.h index 1db3ae912..6aa8794bf 100644 --- a/client/gui/EventDispatcher.h +++ b/client/gui/EventDispatcher.h @@ -28,6 +28,7 @@ class EventDispatcher EventReceiversList hoverable; EventReceiversList keyinterested; EventReceiversList motioninterested; + EventReceiversList draginterested; EventReceiversList timeinterested; EventReceiversList wheelInterested; EventReceiversList doubleClickInterested; @@ -59,7 +60,9 @@ public: void dispatchMouseLeftButtonReleased(const Point & position); void dispatchMouseScrolled(const Point & distance, const Point & position); void dispatchMouseDoubleClick(const Point & position); - void dispatchMouseMoved(const Point & distance); + void dispatchMouseMoved(const Point & distance, const Point & position); + + void dispatchMouseDragged(const Point & currentPosition, const Point & lastUpdateDistance); void dispatchShowPopup(const Point & position); void dispatchClosePopup(const Point & position); diff --git a/client/gui/EventsReceiver.h b/client/gui/EventsReceiver.h index 9693cd7ed..a4297a064 100644 --- a/client/gui/EventsReceiver.h +++ b/client/gui/EventsReceiver.h @@ -45,7 +45,8 @@ protected: virtual void gesturePinch(const Point & centerPosition, double lastUpdateFactor) {} virtual void wheelScrolled(int distance) {} - virtual void mouseMoved(const Point & cursorPosition) {} + virtual void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) {} + virtual void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) {} /// Called when UI element hover status changes virtual void hover(bool on) {} @@ -84,6 +85,7 @@ public: DOUBLECLICK = 256, TEXTINPUT = 512, GESTURE = 1024, + DRAG = 2048, }; /// Returns true if element is currently hovered by mouse diff --git a/client/mapView/MapViewActions.cpp b/client/mapView/MapViewActions.cpp index 60d476642..270265f15 100644 --- a/client/mapView/MapViewActions.cpp +++ b/client/mapView/MapViewActions.cpp @@ -63,7 +63,7 @@ void MapViewActions::showPopupWindow() adventureInt->onTileRightClicked(tile); } -void MapViewActions::mouseMoved(const Point & cursorPosition) +void MapViewActions::mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) { handleHover(cursorPosition); } diff --git a/client/mapView/MapViewActions.h b/client/mapView/MapViewActions.h index 4bab037bc..ac0f3597d 100644 --- a/client/mapView/MapViewActions.h +++ b/client/mapView/MapViewActions.h @@ -37,6 +37,6 @@ public: void gesturePinch(const Point & centerPosition, double lastUpdateFactor) override; void hover(bool on) override; void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; - void mouseMoved(const Point & cursorPosition) override; + void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override; void wheelScrolled(int distance) override; }; diff --git a/client/widgets/Slider.cpp b/client/widgets/Slider.cpp index d6bbaa309..da36764bd 100644 --- a/client/widgets/Slider.cpp +++ b/client/widgets/Slider.cpp @@ -18,26 +18,17 @@ #include "../gui/CGuiHandler.h" #include "../render/Canvas.h" -void CSlider::sliderClicked() -{ - addUsedEvents(MOVE); -} - -void CSlider::mouseMoved (const Point & cursorPosition) +void CSlider::mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) { double v = 0; if(getOrientation() == Orientation::HORIZONTAL) { - if( std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2+40 || std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2 ) - return; v = cursorPosition.x - pos.x - 24; v *= positions; v /= (pos.w - 48); } else { - if(std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2+40 || std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2 ) - return; v = cursorPosition.y - pos.y - 24; v *= positions; v /= (pos.h - 48); @@ -138,20 +129,16 @@ void CSlider::clickLeft(tribool down, bool previousState) pw = GH.getCursorPosition().y-pos.y-24; rw = pw / (pos.h-48); } - if(pw < -8 || pw > (getOrientation() == Orientation::HORIZONTAL ? pos.w : pos.h) - 40) - return; - // if (rw>1) return; - // if (rw<0) return; + slider->clickLeft(true, slider->isMouseLeftButtonPressed()); scrollTo((int)(rw * positions + 0.5)); return; } - removeUsedEvents(MOVE); } bool CSlider::receiveEvent(const Point &position, int eventType) const { - if (eventType != WHEEL && eventType != GESTURE) + if(eventType != WHEEL && eventType != GESTURE) { return CIntObject::receiveEvent(position, eventType); } @@ -165,7 +152,7 @@ bool CSlider::receiveEvent(const Point &position, int eventType) const } CSlider::CSlider(Point position, int totalw, std::function Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style) - : Scrollable(LCLICK, position, Horizontal ? Orientation::HORIZONTAL : Orientation::VERTICAL ), + : Scrollable(LCLICK | DRAG, position, Horizontal ? Orientation::HORIZONTAL : Orientation::VERTICAL ), capacity(Capacity), amount(Amount), value(Value), @@ -207,7 +194,6 @@ CSlider::CSlider(Point position, int totalw, std::function Moved, int left->addCallback(std::bind(&CSlider::scrollPrev,this)); right->addCallback(std::bind(&CSlider::scrollNext,this)); - slider->addCallback(std::bind(&CSlider::sliderClicked,this)); if(getOrientation() == Orientation::HORIZONTAL) { diff --git a/client/widgets/Slider.h b/client/widgets/Slider.h index d17a48b38..906b9cfac 100644 --- a/client/widgets/Slider.h +++ b/client/widgets/Slider.h @@ -37,7 +37,6 @@ class CSlider : public Scrollable CFunctionList moved; void updateSliderPos(); - void sliderClicked(); public: enum EStyle @@ -71,7 +70,7 @@ public: bool receiveEvent(const Point & position, int eventType) const override; void keyPressed(EShortcut key) override; void clickLeft(tribool down, bool previousState) override; - void mouseMoved (const Point & cursorPosition) override; + void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override; void showAll(Canvas & to) override; /// @param position coordinates of slider diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index b332333e6..78b783dd4 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -69,7 +69,7 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town area(nullptr), stateTimeCounter(BUILD_ANIMATION_FINISHED_TIMEPOINT) { - addUsedEvents(LCLICK | SHOW_POPUP | HOVER | TIME); + addUsedEvents(LCLICK | SHOW_POPUP | MOVE | HOVER | TIME); pos.x += str->pos.x; pos.y += str->pos.y; @@ -108,19 +108,24 @@ const CBuilding * CBuildingRect::getBuilding() bool CBuildingRect::operator<(const CBuildingRect & p2) const { return (str->pos.z) < (p2.str->pos.z); - } void CBuildingRect::hover(bool on) { + if (!area) + return; + if(on) { - addUsedEvents(MOVE); + if(! parent->selectedBuilding //no building hovered + || (*parent->selectedBuilding)<(*this)) //or we are on top + { + parent->selectedBuilding = this; + GH.statusbar()->write(getSubtitle()); + } } else { - removeUsedEvents(MOVE); - if(parent->selectedBuilding == this) { parent->selectedBuilding = nullptr; @@ -133,11 +138,8 @@ void CBuildingRect::clickLeft(tribool down, bool previousState) { if(previousState && getBuilding() && area && !down && (parent->selectedBuilding==this)) { - if(!area->isTransparent(GH.getCursorPosition() - pos.topLeft())) //inside building image - { - auto building = getBuilding(); - parent->buildingClicked(building->bid, building->subId, building->upgrade); - } + auto building = getBuilding(); + parent->buildingClicked(building->bid, building->subId, building->upgrade); } } @@ -145,20 +147,18 @@ void CBuildingRect::showPopupWindow() { if((!area) || (this!=parent->selectedBuilding) || getBuilding() == nullptr) return; - if( !area->isTransparent(GH.getCursorPosition() - pos.topLeft()) ) //inside building image + + BuildingID bid = getBuilding()->bid; + const CBuilding *bld = town->town->buildings.at(bid); + if (bid < BuildingID::DWELL_FIRST) { - BuildingID bid = getBuilding()->bid; - const CBuilding *bld = town->town->buildings.at(bid); - if (bid < BuildingID::DWELL_FIRST) - { - CRClickPopup::createAndPush(CInfoWindow::genText(bld->getNameTranslated(), bld->getDescriptionTranslated()), - std::make_shared(CComponent::building, bld->town->faction->getIndex(), bld->bid)); - } - else - { - int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN; - GH.windows().createAndPushWindow(parent->pos.x+parent->pos.w / 2, parent->pos.y+parent->pos.h /2, town, level); - } + CRClickPopup::createAndPush(CInfoWindow::genText(bld->getNameTranslated(), bld->getDescriptionTranslated()), + std::make_shared(CComponent::building, bld->town->faction->getIndex(), bld->bid)); + } + else + { + int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN; + GH.windows().createAndPushWindow(parent->pos.x+parent->pos.w / 2, parent->pos.y+parent->pos.h /2, town, level); } } @@ -245,28 +245,20 @@ std::string CBuildingRect::getSubtitle()//hover text for building } } -void CBuildingRect::mouseMoved (const Point & cursorPosition) +void CBuildingRect::mouseMoved (const Point & cursorPosition, const Point & lastUpdateDistance) { - if(area && pos.isInside(cursorPosition.x, cursorPosition.y)) - { - if(area->isTransparent(cursorPosition - pos.topLeft())) //hovered pixel is inside this building - { - if(parent->selectedBuilding == this) - { - parent->selectedBuilding = nullptr; - GH.statusbar()->clear(); - } - } - else //inside the area of this building - { - if(! parent->selectedBuilding //no building hovered - || (*parent->selectedBuilding)<(*this)) //or we are on top - { - parent->selectedBuilding = this; - GH.statusbar()->write(getSubtitle()); - } - } - } + hover(true); +} + +bool CBuildingRect::receiveEvent(const Point & position, int eventType) const +{ + if (!pos.isInside(position.x, position.y)) + return false; + + if(area && area->isTransparent(position - pos.topLeft())) + return false; + + return CIntObject::receiveEvent(position, eventType); } CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstance * Town, int level) diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 0adbeac35..d8ab5f42a 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -68,7 +68,8 @@ public: void hover(bool on) override; void clickLeft(tribool down, bool previousState) override; void showPopupWindow() override; - void mouseMoved (const Point & cursorPosition) override; + void mouseMoved (const Point & cursorPosition, const Point & lastUpdateDistance) override; + bool receiveEvent(const Point & position, int eventType) const override; void tick(uint32_t msPassed) override; void show(Canvas & to) override; void showAll(Canvas & to) override; diff --git a/client/windows/CQuestLog.h b/client/windows/CQuestLog.h index 6fed47ad6..412951477 100644 --- a/client/windows/CQuestLog.h +++ b/client/windows/CQuestLog.h @@ -66,7 +66,7 @@ class CQuestMinimap : public CMinimap void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface void iconClicked(); - void mouseMoved (const Point & cursorPosition) override{}; + void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override{}; public: const QuestInfo * currentQuest;