| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: Mouse.cpp ////////////////////////////////////////////////////////////////////////////////
- // Created: Colin Day, June 2001
- // Desc: Basic mouse interactions
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/Debug.h"
- #include "Common/MessageStream.h"
- #include "Common/GameEngine.h"
- #include "Common/GlobalData.h"
- #include "Common/INI.h"
- #include "GameClient/Display.h"
- #include "GameClient/DisplayStringManager.h"
- #include "GameClient/GameClient.h"
- #include "GameClient/GameText.h"
- #include "GameClient/GameWindow.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/Keyboard.h"
- #include "GameClient/Mouse.h"
- #include "GameClient/GlobalLanguage.h"
- #include "GameLogic/ScriptEngine.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
- Mouse *TheMouse = NULL;
- const char *Mouse::RedrawModeName[RM_MAX] = {
- "Mouse:Windows",
- "Mouse:W3D",
- "Mouse:Poly",
- "Mouse:DX8",
- };
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- static const FieldParse TheMouseCursorFieldParseTable[] =
- {
- { "CursorText", INI::parseAsciiString, NULL, offsetof( CursorInfo, cursorText ) },
- { "CursorTextColor", INI::parseRGBAColorInt, NULL, offsetof( CursorInfo, cursorTextColor ) },
- { "CursorTextDropColor", INI::parseRGBAColorInt, NULL, offsetof( CursorInfo, cursorTextDropColor ) },
- { "W3DModel", INI::parseAsciiString, NULL, offsetof( CursorInfo, W3DModelName ) },
- { "W3DAnim", INI::parseAsciiString, NULL, offsetof( CursorInfo, W3DAnimName ) },
- { "W3DScale", INI::parseReal, NULL, offsetof( CursorInfo, W3DScale ) },
- { "Loop", INI::parseBool, NULL, offsetof( CursorInfo, loop ) },
- { "Image", INI::parseAsciiString, NULL, offsetof( CursorInfo, imageName ) },
- { "Texture", INI::parseAsciiString, NULL, offsetof( CursorInfo, textureName ) },
- { "HotSpot", INI::parseICoord2D, NULL, offsetof( CursorInfo, hotSpotPosition ) },
- { "Frames", INI::parseInt, NULL, offsetof( CursorInfo, numFrames ) },
- { "FPS", INI::parseReal, NULL, offsetof( CursorInfo, fps)},
- { "Directions", INI::parseInt, NULL, offsetof( CursorInfo, numDirections ) },
- };
- static const FieldParse TheMouseFieldParseTable[] =
- {
- { "TooltipFontName", INI::parseAsciiString,NULL, offsetof( Mouse, m_tooltipFontName ) },
- { "TooltipFontSize", INI::parseInt, NULL, offsetof( Mouse, m_tooltipFontSize ) },
- { "TooltipFontIsBold", INI::parseBool, NULL, offsetof( Mouse, m_tooltipFontIsBold ) },
- { "TooltipAnimateBackground", INI::parseBool, NULL, offsetof( Mouse, m_tooltipAnimateBackground ) },
- { "TooltipFillTime", INI::parseInt, NULL, offsetof( Mouse, m_tooltipFillTime ) },
- { "TooltipDelayTime", INI::parseInt, NULL, offsetof( Mouse, m_tooltipDelayTime ) },
- { "TooltipTextColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorText ) },
- { "TooltipHighlightColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorHighlight ) },
- { "TooltipShadowColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorShadow ) },
- { "TooltipBackgroundColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorBackground ) },
- { "TooltipBorderColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorBorder ) },
- { "TooltipWidth", INI::parsePercentToReal,NULL, offsetof( Mouse, m_tooltipWidth ) },
- { "CursorMode", INI::parseInt, NULL, offsetof( Mouse, m_currentRedrawMode ) },
- { "UseTooltipAltTextColor", INI::parseBool, NULL, offsetof( Mouse, m_useTooltipAltTextColor ) },
- { "UseTooltipAltBackColor", INI::parseBool, NULL, offsetof( Mouse, m_useTooltipAltBackColor ) },
- { "AdjustTooltipAltColor", INI::parseBool, NULL, offsetof( Mouse, m_adjustTooltipAltColor ) },
- { "OrthoCamera", INI::parseBool, NULL, offsetof( Mouse, m_orthoCamera ) },
- { "OrthoZoom", INI::parseReal, NULL, offsetof( Mouse, m_orthoZoom ) },
- { "DragTolerance", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragTolerance) },
- { "DragTolerance3D", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragTolerance3D) },
- { "DragToleranceMS", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragToleranceMS) },
- };
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- /** Move the mouse in either relative or absolute coords */
- //-------------------------------------------------------------------------------------------------
- void Mouse::moveMouse( Int x, Int y, Int relOrAbs )
- {
- if( relOrAbs == MOUSE_MOVE_RELATIVE )
- {
- m_currMouse.pos.x += x;
- m_currMouse.pos.y += y;
- }
- else
- {
- m_currMouse.pos.x = x;
- m_currMouse.pos.y = y;
- }
- if( m_currMouse.pos.x > m_maxX )
- m_currMouse.pos.x = m_maxX;
- else if( m_currMouse.pos.x < m_minX )
- m_currMouse.pos.x = m_minX;
- if( m_currMouse.pos.y > m_maxY )
- m_currMouse.pos.y = m_maxY;
- else if( m_currMouse.pos.y < m_minY )
- m_currMouse.pos.y = m_minY;
- } // end moveMouse
- //-------------------------------------------------------------------------------------------------
- /** Get the current information for the mouse from the device */
- //-------------------------------------------------------------------------------------------------
- void Mouse::updateMouseData( )
- {
- static Bool busy = FALSE;
- Int index = 0;
- UnsignedByte result;
- // prevent reentrancy in the event we make this mouse multi-threaded
- if( busy == FALSE )
- {
- busy = TRUE;
- // Get latest mouse events from DirectX
- do
- {
- do
- {
- result = getMouseEvent( &m_mouseEvents[ index ], TRUE );
- }
- while( result == MOUSE_LOST );
- index++;
- }
- while( (result != MOUSE_NONE) &&
- (index < sizeof( m_mouseEvents ) / sizeof( MouseIO )) );
- busy = FALSE;
- } // end if
- if( index > 0 )
- m_eventsThisFrame = index - 1;
- else
- m_eventsThisFrame = 0;
- if( index != 0 )
- m_deadInputFrame = m_inputFrame;
- } // end updateMouseData
- //-------------------------------------------------------------------------------------------------
- /** Combine mouse events into the main mouse variables */
- //-------------------------------------------------------------------------------------------------
- void Mouse::processMouseEvent( Int index )
- {
- Int movementType;
- m_currMouse.leftEvent = MOUSE_EVENT_NONE;
- m_currMouse.rightEvent = MOUSE_EVENT_NONE;
- m_currMouse.middleEvent = MOUSE_EVENT_NONE;
- m_currMouse.wheelPos = 0;
- // what type of movement commands are we setup for
- if( m_inputMovesAbsolute == TRUE )
- movementType = MOUSE_MOVE_ABSOLUTE;
- else
- movementType = MOUSE_MOVE_RELATIVE;
- // set the time of this event to the correct time
- m_currMouse.time = m_mouseEvents[ index ].time;
- if( index == 0 )
- checkForDrag();
- // add Mouse Position Changes to Master Position
- moveMouse( m_mouseEvents[ index ].pos.x,
- m_mouseEvents[ index ].pos.y,
- movementType );
- // Cumulate Wheel Adjustments
- m_currMouse.wheelPos += m_mouseEvents[ index ].wheelPos;
- // Check Left Mouse State
- if( m_mouseEvents[ index ].leftFrame )
- {
- if( m_currMouse.leftState != m_mouseEvents[ index ].leftState )
- {
- // State Change
- if( m_mouseEvents[ index ].leftState == MBS_Down )
- {
- // Mouse Down
- m_currMouse.leftEvent = GWM_LEFT_DOWN;
- m_currMouse.leftState = MBS_Down;
- m_currMouse.leftFrame = m_inputFrame;
- }
- else if ( m_mouseEvents[ index ].leftState == MBS_DoubleClick )
- {
- // Mouse Double Click
- m_currMouse.leftEvent = GWM_LEFT_DOUBLE_CLICK;
- m_currMouse.leftState = MBS_DoubleClick;
- m_currMouse.leftFrame = m_inputFrame;
- }
- else
- {
- // Mouse Up
- m_currMouse.leftEvent = GWM_LEFT_UP;
- m_currMouse.leftState = MBS_Up;
- m_currMouse.leftFrame = m_inputFrame;
- }
- }
- }
- else if( m_currMouse.leftState != MBS_Up &&
- ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
- (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
- {
- m_currMouse.leftEvent = GWM_LEFT_DRAG;
- }
- // Check Right Mouse State
- if( m_mouseEvents[ index ].rightFrame )
- {
- if( m_currMouse.rightState != m_mouseEvents[ index ].rightState )
- {
- // State Change
- if( m_mouseEvents[ index ].rightState == MBS_Down )
- {
- // Mouse Down
- m_currMouse.rightEvent = GWM_RIGHT_DOWN;
- m_currMouse.rightState = MBS_Down;
- m_currMouse.rightFrame = m_inputFrame;
- }
- else if( m_mouseEvents[ index ].rightState == MBS_DoubleClick )
- {
- // Mouse Double Click
- m_currMouse.rightEvent = GWM_RIGHT_DOUBLE_CLICK;
- m_currMouse.rightState = MBS_DoubleClick;
- m_currMouse.rightFrame = m_inputFrame;
- }
- else
- {
- // Mouse Up
- m_currMouse.rightEvent = GWM_RIGHT_UP;
- m_currMouse.rightState = MBS_Up;
- m_currMouse.rightFrame = m_inputFrame;
- }
- }
- }
- else if( m_currMouse.rightState != MBS_Up &&
- ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
- (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
- {
- m_currMouse.rightEvent = GWM_RIGHT_DRAG;
- }
- // Check Middle Mouse State
- if( m_mouseEvents[ index ].middleFrame )
- {
- if( m_currMouse.middleState != m_mouseEvents[index].middleState )
- {
- // State Change
- if( m_mouseEvents[index].middleState == MBS_Down )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DOWN;
- m_currMouse.middleState = MBS_Down;
- m_currMouse.middleFrame = m_inputFrame;
- }
- else if( m_mouseEvents[index].middleState == MBS_DoubleClick )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DOUBLE_CLICK;
- m_currMouse.middleState = MBS_DoubleClick;
- m_currMouse.middleFrame = m_inputFrame;
- }
- else
- {
- // Mouse Up
- m_currMouse.middleEvent = GWM_MIDDLE_UP;
- m_currMouse.middleState = MBS_Up;
- m_currMouse.middleFrame = m_inputFrame;
- }
- }
- }
- else if( m_currMouse.middleState != MBS_Up &&
- ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
- (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
- }
- m_currMouse.deltaPos.x = m_currMouse.pos.x - m_prevMouse.pos.x;
- m_currMouse.deltaPos.y = m_currMouse.pos.y - m_prevMouse.pos.y;
- // DEBUG_LOG(("Mouse dx %d, dy %d, index %d, frame %d\n", m_currMouse.deltaPos.x, m_currMouse.deltaPos.y, index, m_inputFrame));
- // // check if mouse is still and flag tooltip
- // if( ((dx*dx) + (dy*dy)) < CURSOR_MOVE_TOL_SQ )
- // {
- // // cursor is still
- // //m_stillTime++;
- // Int delay = m_tooltipDelayTime;
- // if(m_tooltipDelay >= 0 )
- // delay = m_tooltipDelay;
- //
- // if( now - m_stillTime >= delay )
- // {
- // if (!m_displayTooltip)
- // {
- // m_highlightPos = 0;
- // m_highlightUpdateStart = timeGetTime();
- // }
- //
- // // display tooltip for current window
- // m_displayTooltip = TRUE;
- // }
- // }
- // else
- // {
- // // cursor moved
- // //m_stillTime = 0;
- // m_stillTime = now;
- // m_displayTooltip = FALSE;
- // }
- m_prevMouse = m_currMouse;
- } // end processMouseEvent
- //-------------------------------------------------------------------------------------------------
- /** Check for mouse drag */
- //-------------------------------------------------------------------------------------------------
- void Mouse::checkForDrag( void )
- {
- if( m_currMouse.leftState &&
- ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
- (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
- {
- m_currMouse.leftEvent = GWM_LEFT_DRAG;
- }
- if( m_currMouse.rightState &&
- ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
- (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
- {
- m_currMouse.rightEvent = GWM_RIGHT_DRAG;
- }
- if( m_currMouse.middleState &&
- ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
- (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
- }
- } // end checkForDrag
- //-------------------------------------------------------------------------------------------------
- /** Check for mouse click, using allowed drag forgiveness */
- //-------------------------------------------------------------------------------------------------
- Bool Mouse::isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick)
- {
- ICoord2D delta;
- delta.x = anchor->x - dest->x;
- delta.y = anchor->y - dest->y;
- // 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)
- {
- return FALSE;
- }
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- CursorInfo::CursorInfo( void )
- {
- // Added Sadullah Nader
- // Initializations missing and needed
-
- cursorName.clear();
- cursorText.clear();
- cursorTextColor.red = cursorTextColor.green = cursorTextColor.blue = 0;
- cursorTextDropColor.red = cursorTextDropColor.blue = cursorTextDropColor.green = 0;
-
- //
- textureName.clear();
- imageName.clear();
- W3DModelName.clear();
- W3DAnimName.clear();
- W3DScale = 1.0f;
- loop = TRUE;
- //Assume hotspot is at the center of a 32x32 image.
- hotSpotPosition.x=16;
- hotSpotPosition.y=16;
- numFrames = 1; //assume no animation
- fps=20.0f;
- numDirections=1;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- Mouse::Mouse( void )
- {
- // device info
- m_numButtons = 0;
- m_numAxes = 0;
- m_forceFeedback = FALSE;
-
- //Added By Sadullah Nader
- //Initializations missing and needed
- m_dragTolerance = 0;
- m_dragTolerance3D = 0;
- m_dragToleranceMS = 0;
- //
-
- //m_tooltipString.clear(); // redundant
- m_displayTooltip = FALSE;
- m_tooltipDisplayString = NULL;
- m_tooltipDelay = -1; // default value
- // initialize all the mouse io data
- memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
- memset( &m_currMouse, 0, sizeof( m_currMouse ) );
- memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
- m_minX = 0;
- m_maxX = 0;
- m_minY = 0;
- m_maxY = 0;
- m_eventsThisFrame = 0;
- m_inputFrame = 0;
- m_deadInputFrame =0;
- m_inputMovesAbsolute = FALSE;
- m_currentCursor = ARROW;
- if (TheGlobalData && TheGlobalData->m_winCursors)
- m_currentRedrawMode = RM_WINDOWS;
- else
- m_currentRedrawMode = RM_W3D;//RM_WINDOWS;
- m_visible = FALSE;
- m_tooltipFontName = "Times New Roman";
- m_tooltipFontSize = 12;
- m_tooltipFontIsBold = FALSE;
- m_tooltipAnimateBackground = TRUE;
- m_tooltipFillTime = 50;
- m_tooltipDelayTime = 50;
- #define setColor(x, r, g, b, a) { x.red = r; x.green = g; x.blue = b; x.alpha = a; }
- setColor(m_tooltipColorText, 220, 220, 220, 255);
- setColor(m_tooltipColorHighlight, 255, 255, 0, 255);
- setColor(m_tooltipColorShadow, 0, 0, 0, 255);
- setColor(m_tooltipColorBackground, 20, 20, 0, 127);
- setColor(m_tooltipColorBorder, 0, 0, 0, 255);
- #undef setColor
- m_tooltipWidth = 15.0f;
- m_lastTooltipWidth = 0.0f;
- m_useTooltipAltTextColor = FALSE;
- m_useTooltipAltBackColor = FALSE;
- m_adjustTooltipAltColor = FALSE;
- m_orthoCamera = FALSE;
- m_orthoZoom = 1.0f;
- m_isTooltipEmpty = TRUE;
- m_cursorTextDisplayString = NULL;
- m_cursorTextColor.red = 255;
- m_cursorTextColor.green = 255;
- m_cursorTextColor.blue = 255;
- m_cursorTextColor.alpha = 255;
- m_cursorTextDropColor.red = 255;
- m_cursorTextDropColor.green = 255;
- m_cursorTextDropColor.blue = 255;
- m_cursorTextDropColor.alpha = 255;
-
- m_highlightPos = 0;
- m_highlightUpdateStart = 0;
- m_stillTime = 0;
- m_tooltipTextColor.red = 255;
- m_tooltipTextColor.green = 255;
- m_tooltipTextColor.blue = 255;
- m_tooltipTextColor.alpha = 255;
- m_tooltipBackColor.red = 0;
- m_tooltipBackColor.green = 0;
- m_tooltipBackColor.blue = 0;
- m_tooltipBackColor.alpha = 255;
- } // end Mouse
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- Mouse::~Mouse( void )
- {
- if(m_tooltipDisplayString)
- TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
- m_tooltipDisplayString = NULL;
- if( m_cursorTextDisplayString )
- TheDisplayStringManager->freeDisplayString( m_cursorTextDisplayString );
- m_cursorTextDisplayString = NULL;
- } // end ~Mouse
- /**Had to move this out of main init() because I need this data to properly initialize
- the Win32 version of the mouse (by preloading resources before D3D device is created).*/
- void Mouse::parseIni(void)
- {
- INI ini;
- ini.load( AsciiString( "Data\\INI\\Mouse.ini" ), INI_LOAD_OVERWRITE, NULL );
- }
- //-------------------------------------------------------------------------------------------------
- /** Initialize the mouse */
- //-------------------------------------------------------------------------------------------------
- void Mouse::init( void )
- {
- if (TheGlobalData && TheGlobalData->m_winCursors)
- m_currentRedrawMode = RM_WINDOWS;
- // device info
- m_numButtons = 2; // by default just have 2 buttons
- m_numAxes = 2; // by default a normal mouse moves in a 2d plane
- m_forceFeedback = FALSE;
- mouseNotifyResolutionChange();
- m_tooltipString.clear(); // redundant
- m_displayTooltip = FALSE;
- // initialize all the mouse io data
- memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
- memset( &m_currMouse, 0, sizeof( m_currMouse ) );
- memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
- m_minX = 0;
- m_maxX = 799;
- m_minY = 0;
- m_maxY = 599;
- m_inputFrame = 0;
- m_deadInputFrame =0;
- m_inputMovesAbsolute = FALSE;
- m_eventsThisFrame = 0;
- m_currentCursor = ARROW;
- // allocate a new display string
- m_cursorTextDisplayString = TheDisplayStringManager->newDisplayString();
- } // end init
- //-------------------------------------------------------------------------------------------------
- /** Tell mouse system display resolution changed. */
- //-------------------------------------------------------------------------------------------------
- void Mouse::mouseNotifyResolutionChange( void )
- {
- if(m_tooltipDisplayString)
- TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
- m_tooltipDisplayString = NULL;
- m_tooltipDisplayString = TheDisplayStringManager->newDisplayString();
- if (TheGlobalLanguageData && TheGlobalLanguageData->m_tooltipFontName.name.isNotEmpty())
- {
- m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
- TheGlobalLanguageData->m_tooltipFontName.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_tooltipFontName.size),
- TheGlobalLanguageData->m_tooltipFontName.bold) );
- }
- else
- {
- m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
- m_tooltipFontName,
- TheGlobalLanguageData->adjustFontSize(m_tooltipFontSize),
- m_tooltipFontIsBold ) );
- }
- m_tooltipDisplayString->setWordWrap(120);
- } // end reset
- //-------------------------------------------------------------------------------------------------
- /** Reset mouse system */
- //-------------------------------------------------------------------------------------------------
- void Mouse::reset( void )
- {
- ///@ todo Write Mouse::reset() if there needs to be anything here
- // reset the text of the cursor text
- m_cursorTextDisplayString->reset();
- } // end reset
- //-------------------------------------------------------------------------------------------------
- /** Update the states of the mouse position and buttons */
- //-------------------------------------------------------------------------------------------------
- void Mouse::update( void )
- {
- // increment input frame
- m_inputFrame++;
- // update the mouse data
- updateMouseData( );
- } // end update
- //-------------------------------------------------------------------------------------------------
- /** Given the current state of this input device, turn the raw input
- * data into raw stream messages and place those messages on the stream.
- * NOTE that the click messages replace up messages in the mouse, so we
- * are going to propagate those click messages in addition to up messages */
- //-------------------------------------------------------------------------------------------------
- void Mouse::createStreamMessages( void )
- {
- // santiy
- if( TheMessageStream == NULL )
- return; // no place to put messages
- GameMessage *msg = NULL;
- UnsignedInt now = timeGetTime();
- // basic position messages are always created
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_POSITION );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- Int delay = m_tooltipDelayTime;
- if(m_tooltipDelay >= 0 )
- delay = m_tooltipDelay;
-
- if( now - m_stillTime >= delay )
- {
- if (!m_displayTooltip)
- {
- m_highlightPos = 0;
- m_highlightUpdateStart = timeGetTime();
- }
- // display tooltip for current window
- m_displayTooltip = TRUE;
- }
- else
- {
- //DEBUG_LOG(("%d %d %d %d\n", TheGameClient->getFrame(), delay, now, m_stillTime));
- m_displayTooltip = FALSE;
- }
-
- for (Int i = 0; i < m_eventsThisFrame; ++i)
- {
- processMouseEvent(i);
- if (m_currMouse.deltaPos.x || m_currMouse.deltaPos.y)
- m_stillTime = now;
- // button messages
- msg = NULL;
- switch( m_currMouse.leftEvent )
- {
- case GWM_LEFT_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_LEFT_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_LEFT_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_LEFT_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
- } // end switch
- msg = NULL;
- switch( m_currMouse.middleEvent )
- {
- //-------------------------------------------------------------------------
- case GWM_MIDDLE_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_MIDDLE_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_MIDDLE_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_MIDDLE_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
- } // end switch
- msg = NULL;
- switch( m_currMouse.rightEvent )
- {
- //-------------------------------------------------------------------------
- case GWM_RIGHT_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_RIGHT_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_RIGHT_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
- case GWM_RIGHT_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
- } // end switch
- // wheel pos
- msg = NULL;
- if( m_currMouse.wheelPos != 0 )
- {
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- } // end if
-
- } // end for
- } // end createStreamMessages
- //-------------------------------------------------------------------------------------------------
- /** Set the string to display at the cursor for the tooltip */
- //-------------------------------------------------------------------------------------------------
- void Mouse::setCursorTooltip( UnicodeString tooltip, Int delay, const RGBColor *color, Real width )
- {
- //DEBUG_LOG(("%d Tooltip: %ls\n", TheGameClient->getFrame(), tooltip.str()));
- m_isTooltipEmpty = tooltip.isEmpty();
- m_tooltipDelay = delay;
- Bool forceRecalc = FALSE;
- if ( !tooltip.isEmpty() && width != m_lastTooltipWidth )
- {
- forceRecalc = TRUE;
- Int widthInPixels = (Int)(TheDisplay->getWidth()*m_tooltipWidth*width);
- if (widthInPixels < 10)
- {
- widthInPixels = 120;
- }
- else if (widthInPixels > TheDisplay->getWidth())
- {
- widthInPixels = TheDisplay->getWidth();
- }
- //DEBUG_LOG(("Setting tooltip width to %d pixels (%g%% of the normal tooltip width)\n", widthInPixels, width*100));
- m_tooltipDisplayString->setWordWrap( widthInPixels );
- m_lastTooltipWidth = width;
- }
- if (forceRecalc || !m_isTooltipEmpty && tooltip.compare(m_tooltipDisplayString->getText()))
- {
- m_tooltipDisplayString->setText(tooltip);
- //DEBUG_LOG(("Tooltip: %ls\n", tooltip.str()));
- }
- if (color)
- {
- if (m_useTooltipAltTextColor)
- {
- if (m_adjustTooltipAltColor)
- {
- m_tooltipTextColor.red = REAL_TO_INT((color->red + 1.0f) * 255.0f / 2.0f);
- m_tooltipTextColor.green = REAL_TO_INT((color->green + 1.0f) * 255.0f / 2.0f);
- m_tooltipTextColor.blue = REAL_TO_INT((color->blue + 1.0f) * 255.0f / 2.0f);
- }
- else
- {
- m_tooltipTextColor.red = REAL_TO_INT(color->red * 255.0f);
- m_tooltipTextColor.green = REAL_TO_INT(color->green * 255.0f);
- m_tooltipTextColor.blue = REAL_TO_INT(color->blue * 255.0f);
- }
- m_tooltipTextColor.alpha = m_tooltipColorText.alpha;
- }
- if (m_useTooltipAltBackColor)
- {
- if (m_adjustTooltipAltColor)
- {
- m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f * 0.5f);
- m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f * 0.5f);
- m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f * 0.5f);
- }
- else
- {
- m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f);
- m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f);
- m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f);
- }
- m_tooltipBackColor.alpha = m_tooltipColorBackground.alpha;
- }
- }
- else
- {
- m_tooltipTextColor = m_tooltipColorText;
- m_tooltipBackColor = m_tooltipColorBackground;
- }
- } // end setCursorTooltip
- // ------------------------------------------------------------------------------------------------
- /** Set the text for the mouse cursor ... note that this is *NOT* the tooltip text we
- * can set to be at the mouse position */
- // ------------------------------------------------------------------------------------------------
- void Mouse::setMouseText( UnicodeString text,
- const RGBAColorInt *color,
- const RGBAColorInt *dropColor )
- {
- // sanity, if no display string has been created, get out of here
- if( m_cursorTextDisplayString == NULL )
- return;
- // set the text into the cursor display string
- m_cursorTextDisplayString->setText( text );
- // save the colors to draw in
- if( color )
- m_cursorTextColor = *color;
- if( dropColor )
- m_cursorTextDropColor = *dropColor;
- } // end setMouseText
- //-------------------------------------------------------------------------------------------------
- /** Move the mouse to the position */
- //-------------------------------------------------------------------------------------------------
- void Mouse::setPosition( Int x, Int y )
- {
- m_currMouse.pos.x = x;
- m_currMouse.pos.y = y;
- } // end setPosition
- //-------------------------------------------------------------------------------------------------
- /** This default implemtation of SetMouseLimits will just set the limiting
- * rectangle to be the width and height of the game display with the
- * origin in the upper left at (0,0). However, if the game is running
- * in a windowed mode then these limits should reflect the SCREEN
- * coords that the mouse is allowed to move in. Also, if the game is in
- * a window you may want to adjust for any title bar available in
- * the operating system. For system specific limits and windows etc,
- * just override this function in the device implementation of the mouse */
- //-------------------------------------------------------------------------------------------------
- void Mouse::setMouseLimits( void )
- {
- m_minX = 0;
- m_minY = 0;
- if( TheDisplay )
- {
- m_maxX = TheDisplay->getWidth();
- m_maxY = TheDisplay->getHeight();
-
- } // end if
- } // end setMouseLimits
- //-------------------------------------------------------------------------------------------------
- /** Draw the mouse */
- //-------------------------------------------------------------------------------------------------
- void Mouse::draw( void )
- {
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void Mouse::resetTooltipDelay( void )
- {
- m_stillTime = timeGetTime();
- m_displayTooltip = FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- /** Draw the mouse tooltip if one is set */
- //-------------------------------------------------------------------------------------------------
- void Mouse::drawTooltip( void )
- {
- if (TheScriptEngine->getFade()!=ScriptEngine::FADE_NONE) {
- return;
- }
- /// @todo: Still need to put in display logic so it puts the tool tips in a visable position on the edge of the screen
- if( m_displayTooltip && TheDisplay && m_tooltipDisplayString && (m_tooltipDisplayString->getTextLength() > 0) && !m_isTooltipEmpty)
- {
- Int width, xPos;
- Int height, yPos;
- m_tooltipDisplayString->getSize(&width,&height);
- xPos = m_currMouse.pos.x + 20;
- yPos = m_currMouse.pos.y;// + 20;
- if( xPos + width + 4 > m_maxX ) // +4 for spill
- {
- //xPos = m_maxX - width;
- xPos -= 20 + width;
- }
- if( yPos + height + 4 > m_maxY ) // +4 for spill
- {
- //yPos = m_maxY - height;
- yPos -= /*40 +*/ height;
- }
- Int boxWidth = (m_tooltipAnimateBackground)?(min(width, m_highlightPos)):width;
- #define GMC(x) GameMakeColor(x.red, x.green, x.blue, x.alpha)
- #define COLOR(x) GMC(m_tooltipColor##x)
- TheDisplay->drawFillRect(xPos, yPos, boxWidth + 2,height + 2, GMC(m_tooltipBackColor));//GameMakeColor(0,0,0,125));
- TheDisplay->drawOpenRect(xPos, yPos, boxWidth + 2,height + 2, 1.0, COLOR(Border));//GameMakeColor(20,20,20,255));
- // build clip rect
- IRegion2D clipRegion;
- clipRegion.lo.x = xPos+2;
- clipRegion.lo.y = yPos+1;
- clipRegion.hi.x = xPos+2+m_highlightPos;
- clipRegion.hi.y = yPos+1+height;
- m_tooltipDisplayString->setClipRegion(&clipRegion);
- m_tooltipDisplayString->draw(xPos +2, yPos +1, GMC(m_tooltipTextColor), COLOR(Shadow));//GameMakeColor(220,220,220,255),GameMakeColor(20,20,20,125));
- // highlight section
- const Int HIGHLIGHT_WIDTH = 15;
- clipRegion.lo.x = xPos+2+m_highlightPos-HIGHLIGHT_WIDTH;
- clipRegion.lo.y = yPos+1;
- clipRegion.hi.x = xPos+2+m_highlightPos;
- clipRegion.hi.y = yPos+1+height;
- m_tooltipDisplayString->setClipRegion(&clipRegion);
- m_tooltipDisplayString->draw(xPos +2, yPos +1, COLOR(Highlight), COLOR(Shadow));//GameMakeColor(255,255,0,255),GameMakeColor(20,20,20,125));
- // get ready for the next part of the anim
- if (m_highlightPos < width + HIGHLIGHT_WIDTH)
- {
- UnsignedInt now = timeGetTime();
- m_highlightPos = (width*(now-m_highlightUpdateStart))/m_tooltipFillTime;
- }
- } // end if
- } // end drawTooltip
- // ------------------------------------------------------------------------------------------------
- /** Draw the cursor text at the mouse position. Note that this is *NOT* the tooltip text */
- // ------------------------------------------------------------------------------------------------
- void Mouse::drawCursorText( void )
- {
- // sanity
- if( m_cursorTextDisplayString == NULL )
- return;
- // get the colors to draw the text in an acceptable format
- Color color, dropColor;
- color = GameMakeColor( m_cursorTextColor.red,
- m_cursorTextColor.green,
- m_cursorTextColor.blue,
- m_cursorTextColor.alpha );
- dropColor = GameMakeColor( m_cursorTextDropColor.red,
- m_cursorTextDropColor.green,
- m_cursorTextDropColor.blue,
- m_cursorTextDropColor.alpha );
- // get the size of the text to draw
- Int width, height;
- m_cursorTextDisplayString->getSize( &width, &height );
- // draw the text around the cursor position
- Int x, y;
- x = m_currMouse.pos.x - width / 2;
- y = m_currMouse.pos.y - height / 2;
- m_cursorTextDisplayString->draw( x, y, color, dropColor );
- } // end drawCursorText
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Int Mouse::getCursorIndex(const AsciiString& name)
- {
- if (name.isEmpty())
- return INVALID_MOUSE_CURSOR;
- /** @todo This is silly to have to define these names from INI in the code ...
- * that should be changed (CBD) */
- static char *CursorININames[NUM_MOUSE_CURSORS] =
- {
- //"InvalidMouseCursor", // this entry is not actually a mouse cursor, but just a
- // reminder that it does exist
- "None",
- "Normal",
- "Arrow",
- "Scroll",
- "Target",
- "Move",
- "AttackMove",
- "AttackObj",
- "ForceAttackObj",
- "ForceAttackGround",
- "Build",
- "InvalidBuild",
- "GenericInvalid",
- "Select",
- "EnterFriendly",
- "EnterAggressive",
- "SetRallyPoint",
- "GetRepaired",
- "GetHealed",
- "DoRepair",
- "ResumeConstruction",
- "CaptureBuilding",
- "SnipeVehicle",
- "LaserGuidedMissiles",
- "TankHunterTNTAttack",
- "StabAttack",
- "PlaceRemoteCharge",
- "PlaceTimedCharge",
- "Defector",
- #ifdef ALLOW_DEMORALIZE
- "Demoralize",
- #endif
- "Dock",
- #ifdef ALLOW_SURRENDER
- "PickUpPrisoner",
- "ReturnToPrison",
- #endif
- "FireFlame",
- #ifdef ALLOW_SURRENDER
- "FireTranqDarts",
- "FireStunBullets",
- #endif
- "FireBomb",
- "PlaceBeacon",
- "DisguiseAsVehicle",
- "Waypoint",
- "OutRange",
- "StabAttackInvalid",
- "PlaceChargeInvalid",
- "Hack",
- "ParticleUplinkCannon",
- };
- for (Int i=0; i<NUM_MOUSE_CURSORS; ++i)
- {
- if (name.compareNoCase(CursorININames[i]) == 0)
- return i;
- }
- DEBUG_CRASH(( "Mouse::getCursorIndex - Invalid cursor name '%s'\n", name.str() ));
- return INVALID_MOUSE_CURSOR;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void Mouse::setCursor( MouseCursor cursor )
- {
-
- // if cursor has not changed do nothing
- if( m_currentCursor == cursor )
- return;
- // only if we have a display cursor do we do anything with mouse text
- if( m_cursorTextDisplayString != NULL )
- {
- CursorInfo *cursorInfo = &m_cursorInfo[ cursor ];
- //
- // if there is text present into the cursor info, set it into the mouse, otherwise
- // just clear out the text for the cursor text
- //
- if( cursorInfo->cursorText.isEmpty() == FALSE )
- setMouseText( TheGameText->fetch( cursorInfo->cursorText.str() ),
- &(cursorInfo->cursorTextColor),
- &(cursorInfo->cursorTextDropColor) );
- else
- setMouseText( UnicodeString( L"" ), NULL, NULL );
- } // end if
- } // end setCursor
- //-------------------------------------------------------------------------------------------------
- /** Parse MouseCursor entry */
- //-------------------------------------------------------------------------------------------------
- void INI::parseMouseCursorDefinition( INI* ini )
- {
- const char *c;
- AsciiString name;
- // read the name
- c = ini->getNextToken();
- name.set( c );
- if( TheMouse )
- {
- Int index = TheMouse->getCursorIndex(name);
- if (index != Mouse::INVALID_MOUSE_CURSOR)
- {
- CursorInfo *cursorInfo = &(TheMouse->m_cursorInfo[index]);
- cursorInfo->cursorName = name;
- // parse the ini weapon definition
- ini->initFromINI( cursorInfo, TheMouseCursorFieldParseTable );
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Parse MouseCursor entry */
- //-------------------------------------------------------------------------------------------------
- void INI::parseMouseDefinition( INI* ini )
- {
- if( TheMouse )
- {
- // parse the ini weapon definition
- ini->initFromINI( TheMouse, TheMouseFieldParseTable );
- }
- }
|