diff --git a/Core/GameEngine/Include/GameClient/Mouse.h b/Core/GameEngine/Include/GameClient/Mouse.h index 849a933f37f..499ba4d4485 100644 --- a/Core/GameEngine/Include/GameClient/Mouse.h +++ b/Core/GameEngine/Include/GameClient/Mouse.h @@ -321,7 +321,9 @@ class Mouse : public SubsystemInterface void onGameModeChanged(GameMode prev, GameMode next); void onGamePaused(Bool paused); - Bool isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick); + Bool isClick(const ICoord2D &mouseAnchor0, const ICoord2D &mouseAnchor1, UnsignedInt mouseClickTimeMs0, UnsignedInt mouseClickTimeMs1); + + Real getDragToleranceAdjustedForScrollFactor() const; AsciiString m_tooltipFontName; ///< tooltip font Int m_tooltipFontSize; ///< tooltip font diff --git a/Core/GameEngine/Include/GameClient/SelectionXlat.h b/Core/GameEngine/Include/GameClient/SelectionXlat.h index cdb6f56698b..bdeef4039d5 100644 --- a/Core/GameEngine/Include/GameClient/SelectionXlat.h +++ b/Core/GameEngine/Include/GameClient/SelectionXlat.h @@ -53,8 +53,6 @@ class SelectionTranslator : public GameMessageTranslator SelectCountMap m_selectCountMap; - Coord3D m_deselectDownCameraPosition; - Bool selectFriends( Drawable *draw, GameMessage *createTeamMsg, Bool dragSelecting ); Bool killThemKillThemAll( Drawable *draw, GameMessage *killThemAllMsg ); diff --git a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp index a1c2cb97a4e..7114d899745 100644 --- a/Core/GameEngine/Source/GameClient/Input/Mouse.cpp +++ b/Core/GameEngine/Source/GameClient/Input/Mouse.cpp @@ -384,18 +384,19 @@ void Mouse::checkForDrag() //------------------------------------------------------------------------------------------------- /** Check for mouse click, using allowed drag forgiveness */ //------------------------------------------------------------------------------------------------- -Bool Mouse::isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick) +Bool Mouse::isClick(const ICoord2D &mouseAnchor0, const ICoord2D &mouseAnchor1, UnsignedInt mouseClickTimeMs0, UnsignedInt mouseClickTimeMs1) { - ICoord2D delta; - delta.x = anchor->x - dest->x; - delta.y = anchor->y - dest->y; + const ICoord2D mouseAnchorDelta = mouseAnchor1 - mouseAnchor0; + const UnsignedInt timeMsDelta = mouseClickTimeMs1 - mouseClickTimeMs0; + // TheSuperHackers @bugfix Use the adjusted drag tolerance to prevent too far tolerances with high scroll factors, + // because higher scroll speeds will travel further by the delta. + const Real dragTolerance = getDragToleranceAdjustedForScrollFactor(); - // if the mouse hasn't moved further than the tolerance distance - // or the click took less than the tolerance duration - if ( abs(delta.x) > m_dragTolerance - || abs(delta.y) > m_dragTolerance - || currentMouseClick - previousMouseClick > m_dragToleranceMS) + // If the click took less than the tolerance duration + // or the mouse hasn't moved further than the tolerance distance + // TheSuperHackers @bugfix Now compares the distance in a circle instead of a rectangle. + if ( timeMsDelta > m_dragToleranceMS || mouseAnchorDelta.lengthSqr() > sqr(dragTolerance) ) { return FALSE; } @@ -403,6 +404,14 @@ Bool Mouse::isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt pr } +//------------------------------------------------------------------------------------------------- +/** Get the scroll speed factor adjusted drag tolerance */ +//------------------------------------------------------------------------------------------------- +Real Mouse::getDragToleranceAdjustedForScrollFactor() const +{ + return m_dragTolerance * (TheGlobalData->m_keyboardDefaultScrollFactor / TheGlobalData->m_keyboardScrollFactor); +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// diff --git a/Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp index ac77d3c6017..f803e7fe91a 100644 --- a/Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp +++ b/Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp @@ -3884,7 +3884,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage //a bug where you couldn't cancel the sneak attack mode via right click. This only happened when you //didn't have anything selected which is possible via the shortcut bar. Normally, it would get deselected //via the deselect drawable code. - if( TheMouse->isClick(&m_mouseRightDragAnchor, &m_mouseRightDragLift, m_mouseRightDown, m_mouseRightUp) ) + if( TheMouse->isClick(m_mouseRightDragAnchor, m_mouseRightDragLift, m_mouseRightDown, m_mouseRightUp) ) { TheInGameUI->placeBuildAvailable( nullptr, nullptr ); } @@ -3918,7 +3918,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage { // right click is only actioned here if we're in alternate mouse mode if (TheGlobalData->m_useAlternateMouse - && TheMouse->isClick(&m_mouseRightDragAnchor, &m_mouseRightDragLift, m_mouseRightDown, m_mouseRightUp)) + && TheMouse->isClick(m_mouseRightDragAnchor, m_mouseRightDragLift, m_mouseRightDown, m_mouseRightUp)) { // NOTE: RIGHT_CLICK is not transmitted if AREA_SELECTION or DRAWABLE_PICKED occurs. // If we see this msg, no object was clicked on, therefore clicked on ground. diff --git a/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp b/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp index c523e5c2727..a0f74d8c02c 100644 --- a/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp +++ b/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp @@ -264,7 +264,6 @@ SelectionTranslator::SelectionTranslator() m_deselectFeedbackAnchor.x = 0; m_deselectFeedbackAnchor.y = 0; m_lastClick = 0; - m_deselectDownCameraPosition.zero(); m_displayedMaxWarning = FALSE; m_selectCountMap.clear(); @@ -944,13 +943,11 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa //----------------------------------------------------------------------------- case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN: { - // There are three ways in which we can ignore this as a deselect: + // There are two ways in which we can ignore this as a deselect: // 1) 2-D position on screen // 2) Time has exceeded the time which we allow for this to be a click. - // 3) 3-D camera position has changed m_deselectFeedbackAnchor = msg->getArgument( 0 )->pixel; m_lastClick = (UnsignedInt) msg->getArgument( 2 )->integer; - m_deselectDownCameraPosition = TheTacticalView->getPosition(); break; } @@ -958,14 +955,11 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa //----------------------------------------------------------------------------- case GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP: { - Coord3D cameraPos = TheTacticalView->getPosition(); - cameraPos.sub(m_deselectDownCameraPosition); - ICoord2D pixel = msg->getArgument( 0 )->pixel; UnsignedInt currentTime = (UnsignedInt) msg->getArgument( 2 )->integer; // right click behavior (not right drag) - if (TheMouse->isClick(&m_deselectFeedbackAnchor, &pixel, m_lastClick, currentTime)) + if (TheMouse->isClick(m_deselectFeedbackAnchor, pixel, m_lastClick, currentTime)) { //Added support to cancel the GUI command without deselecting the unit(s) involved //when you right click. diff --git a/Core/Libraries/Include/Lib/BaseType.h b/Core/Libraries/Include/Lib/BaseType.h index 0c68bc9e2ad..e4db2ff942e 100644 --- a/Core/Libraries/Include/Lib/BaseType.h +++ b/Core/Libraries/Include/Lib/BaseType.h @@ -298,8 +298,55 @@ struct Coord2D Real toAngle() const; ///< turn 2D vector into angle (where angle 0 is down the +x axis) + void add( const Coord2D &a ) + { + x += a.x; + y += a.y; + } + + void sub( const Coord2D &a ) + { + x -= a.x; + y -= a.y; + } + + void operator+=( const Coord2D &a ) + { + add(a); + } + + void operator-=( const Coord2D &a ) + { + sub(a); + } + + void set( const Coord2D &a ) + { + x = a.x; + y = a.y; + } + + void set( Real ax, Real ay ) + { + x = ax; + y = ay; + } }; +inline Coord2D operator+( const Coord2D &a, const Coord2D &b ) +{ + Coord2D c = a; + c.add(b); + return c; +} + +inline Coord2D operator-( const Coord2D &a, const Coord2D &b ) +{ + Coord2D c = a; + c.sub(b); + return c; +} + inline Real Coord2D::toAngle() const { #if RTS_GENERALS /*&& RETAIL_COMPATIBLE_CRC*/ @@ -376,8 +423,57 @@ struct ICoord2D } Int length() const { return (Int)sqrt( (double)(x*x + y*y) ); } + Real lengthSqr() const { return x*x + y*y; } + + void add( const ICoord2D &a ) + { + x += a.x; + y += a.y; + } + + void sub( const ICoord2D &a ) + { + x -= a.x; + y -= a.y; + } + + void operator+=( const ICoord2D &a ) + { + add(a); + } + + void operator-=( const ICoord2D &a ) + { + sub(a); + } + + void set( const ICoord2D &a ) + { + x = a.x; + y = a.y; + } + + void set( Int ax, Int ay ) + { + x = ax; + y = ay; + } }; +inline ICoord2D operator+( const ICoord2D &a, const ICoord2D &b ) +{ + ICoord2D c = a; + c.add(b); + return c; +} + +inline ICoord2D operator-( const ICoord2D &a, const ICoord2D &b ) +{ + ICoord2D c = a; + c.sub(b); + return c; +} + struct Region2D { Coord2D lo, hi; // bounds of 2D rectangular region @@ -471,6 +567,16 @@ struct Coord3D z -= a.z; } + void operator+=( const Coord3D &a ) + { + add(a); + } + + void operator-=( const Coord3D &a ) + { + sub(a); + } + void set( const Coord3D &a ) { x = a.x; @@ -507,6 +613,20 @@ struct Coord3D } }; +inline Coord3D operator+( const Coord3D &a, const Coord3D &b ) +{ + Coord3D c = a; + c.add(b); + return c; +} + +inline Coord3D operator-( const Coord3D &a, const Coord3D &b ) +{ + Coord3D c = a; + c.sub(b); + return c; +} + struct ICoord3D { Int x, y, z; @@ -524,8 +644,60 @@ struct ICoord3D { return x == value && y == value && z == value; } + + void add( const ICoord3D &a ) + { + x += a.x; + y += a.y; + z += a.z; + } + + void sub( const ICoord3D &a ) + { + x -= a.x; + y -= a.y; + z -= a.z; + } + + void operator+=( const ICoord3D &a ) + { + add(a); + } + + void operator-=( const ICoord3D &a ) + { + sub(a); + } + + void set( const ICoord3D &a ) + { + x = a.x; + y = a.y; + z = a.z; + } + + void set( Int ax, Int ay, Int az ) + { + x = ax; + y = ay; + z = az; + } }; +inline ICoord3D operator+( const ICoord3D &a, const ICoord3D &b ) +{ + ICoord3D c = a; + c.add(b); + return c; +} + +inline ICoord3D operator-( const ICoord3D &a, const ICoord3D &b ) +{ + ICoord3D c = a; + c.sub(b); + return c; +} + // For alternative see AABoxClass struct Region3D {