diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h index 675fd35f8de..097e2752982 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h @@ -448,7 +448,7 @@ friend class Drawable; // for selection/deselection transactions // Drawable selection mechanisms virtual void selectDrawable( Drawable *draw ); ///< Mark given Drawable as "selected" virtual void deselectDrawable( Drawable *draw ); ///< Clear "selected" status from Drawable - virtual void deselectAllDrawables( Bool postMsg = true ); ///< Clear the "select" flag from all drawables + virtual void deselectAllDrawables( Bool updateGameLogic = true ); ///< Clear the "select" flag from all drawables virtual Int getSelectCount() { return m_selectCount; } ///< Get count of currently selected drawables virtual Int getMaxSelectCount() { return m_maxSelectCount; } ///< Get the max number of selected drawables virtual UnsignedInt getFrameSelectionChanged() { return m_frameSelectionChanged; } ///< Get the max number of selected drawables diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/SelectionXlat.h b/GeneralsMD/Code/GameEngine/Include/GameClient/SelectionXlat.h index bf9900a9f42..22256d85dc7 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/SelectionXlat.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/SelectionXlat.h @@ -42,6 +42,7 @@ class SelectionTranslator : public GameMessageTranslator friend Bool killThemKillThemAllWrapper( Drawable *draw, void *userData ); private: + Bool m_pendingDeselection; Bool m_leftMouseButtonIsDown; Bool m_dragSelecting; UnsignedInt m_lastGroupSelTime; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp index 5e2c41a3d48..e9f3f5664ce 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp @@ -646,7 +646,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control, } //deselect other units - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // create a new group. GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 5f3a8b18b27..5627ba3d2a6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -3553,9 +3553,10 @@ void InGameUI::deselectDrawable( Drawable *draw ) //------------------------------------------------------------------------------------------------- /** Clear all drawables' "select" status */ //------------------------------------------------------------------------------------------------- -void InGameUI::deselectAllDrawables( Bool postMsg ) +void InGameUI::deselectAllDrawables( Bool updateGameLogic ) { const DrawableList *selected = getAllSelectedDrawables(); + const Bool emptySelectedDrawables = selected->empty(); // loop through all the selected drawables for ( DrawableListCIt it = selected->begin(); it != selected->end(); ) @@ -3576,16 +3577,14 @@ void InGameUI::deselectAllDrawables( Bool postMsg ) // our selection can no longer consist of exactly one angry mob m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID; - - ///@todo don't we want to not emit this message if there wasn't a group at all? (CBD) - /** @todo also, we probably are sending this message too much, we should come up with - some kind of "selections are dirty" status that we can check once per frame and send - the correct group info over the network ... could be tricky tho (or impossible) given - the order of operations of things happening in the code (CBD) */ - if( postMsg ) + if (updateGameLogic) { - // TheSuperHackers @tweak Originally this message had one boolean argument, but it wasn't used for anything. - TheMessageStream->appendMessage( GameMessage::MSG_DESTROY_SELECTED_GROUP ); + // TheSuperHackers @tweak Only send this message when objects are currently selected. + if (!emptySelectedDrawables) + { + // TheSuperHackers @tweak Originally this message had one boolean argument, but it wasn't used for anything. + TheMessageStream->appendMessage(GameMessage::MSG_DESTROY_SELECTED_GROUP); + } } } @@ -5888,7 +5887,7 @@ void InGameUI::selectNextIdleWorker() if(selectThisObject) { DEBUG_ASSERTCRASH(selectThisObject->getContainedBy() == nullptr, ("InGameUI::selectNextIdleWorker Selected idle object should not be contained")); - deselectAllDrawables(); + deselectAllDrawables(FALSE); GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp index 830faa70ac9..a6bcf3eca1b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp @@ -2585,7 +2585,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage if(newDrawable != nullptr ) { //deselect other units - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // create a new group. GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); @@ -2701,7 +2701,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage if(newDrawable != nullptr ) { //deselect other units - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // select the unit // create a new group. @@ -2814,7 +2814,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage if(newDrawable != nullptr ) { //deselect other units - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // select the unit // create a new group. @@ -2929,7 +2929,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage if(newDrawable != nullptr ) { //deselect other units - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // select the unit // create a new group. @@ -2982,7 +2982,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage if ( heroDraw == nullptr ) break; - TheInGameUI->deselectAllDrawables(); + TheInGameUI->deselectAllDrawables(FALSE); // create a new group. GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp index 3bd19e0762e..bbda06ad681 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp @@ -216,18 +216,6 @@ static Bool canSelectWrapper( Drawable *draw, void *userData ) return CanSelectDrawable( draw, dragSelecting ); } -//----------------------------------------------------------------------------- -/** - * Deselect all drawables, and emit a "TEAM_DESTROY" message, since - * the "team" was the group of currently selected units. - */ -static void deselectAll() -{ - - // deselect it all - TheInGameUI->deselectAllDrawables(); -} - //----------------------------------------------------------------------------- /** * Select the given drawable, without playing its sound. @@ -237,7 +225,7 @@ static Bool selectSingleDrawableWithoutSound( Drawable *draw ) { // since we are single selecting a drawable, unselect everything else - deselectAll(); + TheInGameUI->deselectAllDrawables(); // do the drawable selection TheInGameUI->selectDrawable( draw ); @@ -261,6 +249,7 @@ SelectionTranslator *TheSelectionTranslator = nullptr; //----------------------------------------------------------------------------- SelectionTranslator::SelectionTranslator() { + m_pendingDeselection = FALSE; m_leftMouseButtonIsDown = FALSE; m_dragSelecting = FALSE; m_lastGroupSelTime = 0; @@ -750,7 +739,8 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa { if (!addToGroup) { - deselectAll(); + m_pendingDeselection = FALSE; + TheInGameUI->deselectAllDrawables(FALSE); } GameMessage *newMsg = TheMessageStream->appendMessage(GameMessage::MSG_CREATE_SELECTED_GROUP); @@ -951,7 +941,7 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa { if( !TheInGameUI->getPreventLeftClickDeselectionInAlternateMouseModeForOneClick() ) { - deselectAll(); + m_pendingDeselection = TRUE; m_lastGroupSelGroup = -1; } else @@ -1018,7 +1008,7 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa else if (!TheGlobalData->m_useAlternateMouse) { //No GUI command mode, so deselect everyone if we're in regular mouse mode. - deselectAll(); + TheInGameUI->deselectAllDrawables(); } } } @@ -1330,6 +1320,14 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa #endif } + // TheSuperHackers @tweak Avoid double deselection when selecting a new object with another object selected, + // originally triggered by RAW_MOUSE_LEFT_BUTTON_UP and MOUSE_LEFT_CLICK, respectively. + if (msg->getType() == GameMessage::MSG_MOUSE_LEFT_CLICK && m_pendingDeselection) + { + m_pendingDeselection = FALSE; + TheInGameUI->deselectAllDrawables(); + } + return disp; }