diff --git a/client/VCMI_client.vcxproj b/client/VCMI_client.vcxproj index ec30a83ab..9d0476656 100644 --- a/client/VCMI_client.vcxproj +++ b/client/VCMI_client.vcxproj @@ -292,6 +292,4 @@ - - \ No newline at end of file diff --git a/client/VCMI_client.vcxproj.filters b/client/VCMI_client.vcxproj.filters index d389ba18b..b044f1d67 100644 --- a/client/VCMI_client.vcxproj.filters +++ b/client/VCMI_client.vcxproj.filters @@ -109,17 +109,10 @@ gui - - - - Source Files - + - - Header Files - @@ -254,5 +247,6 @@ gui + \ No newline at end of file diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index c4eb536ad..57345a1e4 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -60,6 +60,7 @@ void CGuiHandler::processLists(const ui16 activityFlag, std::functioncurh->cursorMove(sEvent->motion.x, sEvent->motion.y); handleMouseMotion(sEvent); } - else if (sEvent->type==SDL_MOUSEBUTTONDOWN) + else if(sEvent->type == SDL_MOUSEBUTTONDOWN) { - if(sEvent->button.button == SDL_BUTTON_LEFT) + switch(sEvent->button.button) { - - if(lastClick == sEvent->motion && (SDL_GetTicks() - lastClickTime) < 300) + case SDL_BUTTON_LEFT: + if(lastClick == sEvent->motion && (SDL_GetTicks() - lastClickTime) < 300) { std::list hlp = doubleClickInterested; - for(auto i=hlp.begin(); i != hlp.end() && current; i++) + for(auto i = hlp.begin(); i != hlp.end() && current; i++) { - if(!vstd::contains(doubleClickInterested,*i)) continue; - if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) + if(!vstd::contains(doubleClickInterested, *i)) continue; + if(isItIn(&(*i)->pos, sEvent->motion.x, sEvent->motion.y)) { (*i)->onDoubleClick(); } @@ -282,31 +283,16 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent) lastClick = sEvent->motion; lastClickTime = SDL_GetTicks(); - std::list hlp = lclickable; - for(auto i=hlp.begin(); i != hlp.end() && current; i++) - { - if(!vstd::contains(lclickable,*i)) continue; - if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) - { - prev = (*i)->pressedL; - (*i)->pressedL = true; - (*i)->clickLeft(true, prev); - } - } - } - else if (sEvent->button.button == SDL_BUTTON_RIGHT) - { - std::list hlp = rclickable; - for(auto i=hlp.begin(); i != hlp.end() && current; i++) - { - if(!vstd::contains(rclickable,*i)) continue; - if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) - { - prev = (*i)->pressedR; - (*i)->pressedR = true; - (*i)->clickRight(true, prev); - } - } + handleMouseButtonClick(lclickable, EIntObjMouseBtnType::LEFT, true); + break; + case SDL_BUTTON_RIGHT: + handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, true); + break; + case SDL_BUTTON_MIDDLE: + handleMouseButtonClick(mclickable, EIntObjMouseBtnType::MIDDLE, true); + break; + default: + break; } } else if (sEvent->type == SDL_MOUSEWHEEL) @@ -336,41 +322,45 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent) } } //todo: muiltitouch - else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_LEFT)) + else if(sEvent->type == SDL_MOUSEBUTTONUP) { - std::list hlp = lclickable; - for(auto i=hlp.begin(); i != hlp.end() && current; i++) + switch(sEvent->button.button) { - if(!vstd::contains(lclickable,*i)) continue; - prev = (*i)->pressedL; - (*i)->pressedL = false; - if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) - { - (*i)->clickLeft(false, prev); - } - else - (*i)->clickLeft(boost::logic::indeterminate, prev); - } - } - else if ((sEvent->type==SDL_MOUSEBUTTONUP) && (sEvent->button.button == SDL_BUTTON_RIGHT)) - { - std::list hlp = rclickable; - for(auto i=hlp.begin(); i != hlp.end() && current; i++) - { - if(!vstd::contains(rclickable,*i)) continue; - prev = (*i)->pressedR; - (*i)->pressedR = false; - if (isItIn(&(*i)->pos,sEvent->motion.x,sEvent->motion.y)) - { - (*i)->clickRight(false, prev); - } - else - (*i)->clickRight(boost::logic::indeterminate, prev); + case SDL_BUTTON_LEFT: + handleMouseButtonClick(lclickable, EIntObjMouseBtnType::LEFT, false); + break; + case SDL_BUTTON_RIGHT: + handleMouseButtonClick(rclickable, EIntObjMouseBtnType::RIGHT, false); + break; + case SDL_BUTTON_MIDDLE: + handleMouseButtonClick(mclickable, EIntObjMouseBtnType::MIDDLE, false); + break; } } current = nullptr; } //event end +void CGuiHandler::handleMouseButtonClick(CIntObjectList & interestedObjs, EIntObjMouseBtnType btn, bool isPressed) +{ + auto hlp = interestedObjs; + for(auto i = hlp.begin(); i != hlp.end() && current; i++) + { + if(!vstd::contains(interestedObjs, *i)) continue; + + auto prev = (*i)->mouseState(btn); + if(!isPressed) + (*i)->updateMouseState(btn, isPressed); + if(isItIn(&(*i)->pos, current->motion.x, current->motion.y)) + { + if(isPressed) + (*i)->updateMouseState(btn, isPressed); + (*i)->click(btn, isPressed, prev); + } + else if(!isPressed) + (*i)->click(btn, boost::logic::indeterminate, prev); + } +} + void CGuiHandler::handleMouseMotion(SDL_Event *sEvent) { //sending active, hovered hoverable objects hover() call diff --git a/client/gui/CGuiHandler.h b/client/gui/CGuiHandler.h index 3449dd76c..ad3fef61b 100644 --- a/client/gui/CGuiHandler.h +++ b/client/gui/CGuiHandler.h @@ -10,6 +10,7 @@ class CIntObject; class IUpdateable; class IShowActivatable; class IShowable; +enum class EIntObjMouseBtnType; template struct CondSh; /* @@ -53,6 +54,7 @@ private: //active GUI elements (listening for events CIntObjectList lclickable, rclickable, + mclickable, hoverable, keyinterested, motioninterested, @@ -62,6 +64,7 @@ private: textInterested; + void handleMouseButtonClick(CIntObjectList &interestedObjs, EIntObjMouseBtnType btn, bool isPressed); void processLists(const ui16 activityFlag, std::function *)> cb); public: void handleElementActivate(CIntObject * elem, ui16 activityFlag); diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index 8fa3b3025..40e7c281f 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -16,7 +16,7 @@ CIntObject::CIntObject(int used_, Point pos_): parent(parent_m), active(active_m) { - pressedL = pressedR = hovered = captureAllKeys = strongInterest = false; + hovered = captureAllKeys = strongInterest = false; toNextTick = timerDelay = 0; used = used_; @@ -134,6 +134,23 @@ CIntObject::~CIntObject() parent_m->removeChild(this); } +void CIntObject::click(EIntObjMouseBtnType btn, tribool down, bool previousState) +{ + switch(btn) + { + default: + case EIntObjMouseBtnType::LEFT: + clickLeft(down, previousState); + break; + case EIntObjMouseBtnType::MIDDLE: + clickMiddle(down, previousState); + break; + case EIntObjMouseBtnType::RIGHT: + clickRight(down, previousState); + break; + } +} + void CIntObject::printAtLoc( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=Colors::WHITE*/, SDL_Surface * dst/*=screen*/ ) { graphics->fonts[font]->renderTextLeft(dst, text, kolor, Point(pos.x + x, pos.y + y)); @@ -340,16 +357,9 @@ void CKeyShortcut::keyPressed(const SDL_KeyboardEvent & key) if(vstd::contains(assignedKeys,key.keysym.sym) || vstd::contains(assignedKeys, CGuiHandler::numToDigit(key.keysym.sym))) { - bool prev = pressedL; - if(key.state == SDL_PRESSED) - { - pressedL = true; - clickLeft(true, prev); - } - else - { - pressedL = false; - clickLeft(false, prev); - } + bool prev = mouseState(EIntObjMouseBtnType::LEFT); + updateMouseState(EIntObjMouseBtnType::LEFT, key.state == SDL_PRESSED); + clickLeft(key.state == SDL_PRESSED, prev); + } } diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index 75d8c2507..31f479738 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -61,6 +61,7 @@ public: virtual ~IShowActivatable(){}; //d-tor }; +enum class EIntObjMouseBtnType { LEFT, MIDDLE, RIGHT }; //typedef ui16 ActivityFlag; // Base UI element @@ -73,6 +74,8 @@ class CIntObject : public IShowActivatable //interface object int toNextTick; int timerDelay; + std::map currentMouseState; + void onTimer(int timePassed); //non-const versions of fields to allow changing them in CIntObject @@ -104,13 +107,13 @@ public: CIntObject(int used=0, Point offset=Point()); virtual ~CIntObject(); //d-tor - //l-clicks handling - /*const*/ bool pressedL; //for determining if object is L-pressed - virtual void clickLeft(tribool down, bool previousState){} + void updateMouseState(EIntObjMouseBtnType btn, bool state) { currentMouseState[btn] = state; } + bool mouseState(EIntObjMouseBtnType btn) const { return currentMouseState.count(btn) ? currentMouseState.at(btn) : false; } - //r-clicks handling - /*const*/ bool pressedR; //for determining if object is R-pressed - virtual void clickRight(tribool down, bool previousState){} + virtual void click(EIntObjMouseBtnType btn, tribool down, bool previousState); + virtual void clickLeft(tribool down, bool previousState) {} + virtual void clickRight(tribool down, bool previousState) {} + virtual void clickMiddle(tribool down, bool previousState) {} //hover handling /*const*/ bool hovered; //for determining if object is hovered @@ -138,7 +141,7 @@ public: //double click virtual void onDoubleClick(){} - enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, ALL=0xffff}; + enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, MCLICK=1024, ALL=0xffff}; const ui16 & active; void addUsedEvents(ui16 newActions); void removeUsedEvents(ui16 newActions); diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 1cea6ad3c..2f67737d5 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -587,7 +587,7 @@ void CMinimap::hover(bool on) void CMinimap::mouseMoved(const SDL_MouseMotionEvent & sEvent) { - if (pressedL) + if (mouseState(EIntObjMouseBtnType::LEFT)) moveAdvMapSelection(); } diff --git a/client/widgets/Buttons.cpp b/client/widgets/Buttons.cpp index 8784e0d1a..7abc4a5c5 100644 --- a/client/widgets/Buttons.cpp +++ b/client/widgets/Buttons.cpp @@ -623,7 +623,7 @@ void CSlider::clickLeft(tribool down, bool previousState) return; // if (rw>1) return; // if (rw<0) return; - slider->clickLeft(true, slider->pressedL); + slider->clickLeft(true, slider->mouseState(EIntObjMouseBtnType::LEFT)); moveTo(rw * positions + 0.5); return; }