Mouse.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: Mouse.cpp ////////////////////////////////////////////////////////////////////////////////
  24. // Created: Colin Day, June 2001
  25. // Desc: Basic mouse interactions
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  28. #include "Common/Debug.h"
  29. #include "Common/MessageStream.h"
  30. #include "Common/GameEngine.h"
  31. #include "Common/GlobalData.h"
  32. #include "Common/INI.h"
  33. #include "GameClient/Display.h"
  34. #include "GameClient/DisplayStringManager.h"
  35. #include "GameClient/GameClient.h"
  36. #include "GameClient/GameText.h"
  37. #include "GameClient/GameWindow.h"
  38. #include "GameClient/InGameUI.h"
  39. #include "GameClient/Keyboard.h"
  40. #include "GameClient/Mouse.h"
  41. #include "GameClient/GlobalLanguage.h"
  42. #include "GameLogic/ScriptEngine.h"
  43. #ifdef _INTERNAL
  44. // for occasional debugging...
  45. //#pragma optimize("", off)
  46. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  47. #endif
  48. // PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
  49. Mouse *TheMouse = NULL;
  50. const char *Mouse::RedrawModeName[RM_MAX] = {
  51. "Mouse:Windows",
  52. "Mouse:W3D",
  53. "Mouse:Poly",
  54. "Mouse:DX8",
  55. };
  56. ///////////////////////////////////////////////////////////////////////////////////////////////////
  57. // PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
  58. ///////////////////////////////////////////////////////////////////////////////////////////////////
  59. static const FieldParse TheMouseCursorFieldParseTable[] =
  60. {
  61. { "CursorText", INI::parseAsciiString, NULL, offsetof( CursorInfo, cursorText ) },
  62. { "CursorTextColor", INI::parseRGBAColorInt, NULL, offsetof( CursorInfo, cursorTextColor ) },
  63. { "CursorTextDropColor", INI::parseRGBAColorInt, NULL, offsetof( CursorInfo, cursorTextDropColor ) },
  64. { "W3DModel", INI::parseAsciiString, NULL, offsetof( CursorInfo, W3DModelName ) },
  65. { "W3DAnim", INI::parseAsciiString, NULL, offsetof( CursorInfo, W3DAnimName ) },
  66. { "W3DScale", INI::parseReal, NULL, offsetof( CursorInfo, W3DScale ) },
  67. { "Loop", INI::parseBool, NULL, offsetof( CursorInfo, loop ) },
  68. { "Image", INI::parseAsciiString, NULL, offsetof( CursorInfo, imageName ) },
  69. { "Texture", INI::parseAsciiString, NULL, offsetof( CursorInfo, textureName ) },
  70. { "HotSpot", INI::parseICoord2D, NULL, offsetof( CursorInfo, hotSpotPosition ) },
  71. { "Frames", INI::parseInt, NULL, offsetof( CursorInfo, numFrames ) },
  72. { "FPS", INI::parseReal, NULL, offsetof( CursorInfo, fps)},
  73. { "Directions", INI::parseInt, NULL, offsetof( CursorInfo, numDirections ) },
  74. };
  75. static const FieldParse TheMouseFieldParseTable[] =
  76. {
  77. { "TooltipFontName", INI::parseAsciiString,NULL, offsetof( Mouse, m_tooltipFontName ) },
  78. { "TooltipFontSize", INI::parseInt, NULL, offsetof( Mouse, m_tooltipFontSize ) },
  79. { "TooltipFontIsBold", INI::parseBool, NULL, offsetof( Mouse, m_tooltipFontIsBold ) },
  80. { "TooltipAnimateBackground", INI::parseBool, NULL, offsetof( Mouse, m_tooltipAnimateBackground ) },
  81. { "TooltipFillTime", INI::parseInt, NULL, offsetof( Mouse, m_tooltipFillTime ) },
  82. { "TooltipDelayTime", INI::parseInt, NULL, offsetof( Mouse, m_tooltipDelayTime ) },
  83. { "TooltipTextColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorText ) },
  84. { "TooltipHighlightColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorHighlight ) },
  85. { "TooltipShadowColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorShadow ) },
  86. { "TooltipBackgroundColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorBackground ) },
  87. { "TooltipBorderColor", INI::parseRGBAColorInt, NULL, offsetof( Mouse, m_tooltipColorBorder ) },
  88. { "TooltipWidth", INI::parsePercentToReal,NULL, offsetof( Mouse, m_tooltipWidth ) },
  89. { "CursorMode", INI::parseInt, NULL, offsetof( Mouse, m_currentRedrawMode ) },
  90. { "UseTooltipAltTextColor", INI::parseBool, NULL, offsetof( Mouse, m_useTooltipAltTextColor ) },
  91. { "UseTooltipAltBackColor", INI::parseBool, NULL, offsetof( Mouse, m_useTooltipAltBackColor ) },
  92. { "AdjustTooltipAltColor", INI::parseBool, NULL, offsetof( Mouse, m_adjustTooltipAltColor ) },
  93. { "OrthoCamera", INI::parseBool, NULL, offsetof( Mouse, m_orthoCamera ) },
  94. { "OrthoZoom", INI::parseReal, NULL, offsetof( Mouse, m_orthoZoom ) },
  95. { "DragTolerance", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragTolerance) },
  96. { "DragTolerance3D", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragTolerance3D) },
  97. { "DragToleranceMS", INI::parseUnsignedInt, NULL, offsetof( Mouse, m_dragToleranceMS) },
  98. };
  99. ///////////////////////////////////////////////////////////////////////////////////////////////////
  100. // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
  101. ///////////////////////////////////////////////////////////////////////////////////////////////////
  102. //-------------------------------------------------------------------------------------------------
  103. /** Move the mouse in either relative or absolute coords */
  104. //-------------------------------------------------------------------------------------------------
  105. void Mouse::moveMouse( Int x, Int y, Int relOrAbs )
  106. {
  107. if( relOrAbs == MOUSE_MOVE_RELATIVE )
  108. {
  109. m_currMouse.pos.x += x;
  110. m_currMouse.pos.y += y;
  111. }
  112. else
  113. {
  114. m_currMouse.pos.x = x;
  115. m_currMouse.pos.y = y;
  116. }
  117. if( m_currMouse.pos.x > m_maxX )
  118. m_currMouse.pos.x = m_maxX;
  119. else if( m_currMouse.pos.x < m_minX )
  120. m_currMouse.pos.x = m_minX;
  121. if( m_currMouse.pos.y > m_maxY )
  122. m_currMouse.pos.y = m_maxY;
  123. else if( m_currMouse.pos.y < m_minY )
  124. m_currMouse.pos.y = m_minY;
  125. } // end moveMouse
  126. //-------------------------------------------------------------------------------------------------
  127. /** Get the current information for the mouse from the device */
  128. //-------------------------------------------------------------------------------------------------
  129. void Mouse::updateMouseData( )
  130. {
  131. static Bool busy = FALSE;
  132. Int index = 0;
  133. UnsignedByte result;
  134. // prevent reentrancy in the event we make this mouse multi-threaded
  135. if( busy == FALSE )
  136. {
  137. busy = TRUE;
  138. // Get latest mouse events from DirectX
  139. do
  140. {
  141. do
  142. {
  143. result = getMouseEvent( &m_mouseEvents[ index ], TRUE );
  144. }
  145. while( result == MOUSE_LOST );
  146. index++;
  147. }
  148. while( (result != MOUSE_NONE) &&
  149. (index < sizeof( m_mouseEvents ) / sizeof( MouseIO )) );
  150. busy = FALSE;
  151. } // end if
  152. if( index > 0 )
  153. m_eventsThisFrame = index - 1;
  154. else
  155. m_eventsThisFrame = 0;
  156. if( index != 0 )
  157. m_deadInputFrame = m_inputFrame;
  158. } // end updateMouseData
  159. //-------------------------------------------------------------------------------------------------
  160. /** Combine mouse events into the main mouse variables */
  161. //-------------------------------------------------------------------------------------------------
  162. void Mouse::processMouseEvent( Int index )
  163. {
  164. Int movementType;
  165. m_currMouse.leftEvent = MOUSE_EVENT_NONE;
  166. m_currMouse.rightEvent = MOUSE_EVENT_NONE;
  167. m_currMouse.middleEvent = MOUSE_EVENT_NONE;
  168. m_currMouse.wheelPos = 0;
  169. // what type of movement commands are we setup for
  170. if( m_inputMovesAbsolute == TRUE )
  171. movementType = MOUSE_MOVE_ABSOLUTE;
  172. else
  173. movementType = MOUSE_MOVE_RELATIVE;
  174. // set the time of this event to the correct time
  175. m_currMouse.time = m_mouseEvents[ index ].time;
  176. if( index == 0 )
  177. checkForDrag();
  178. // add Mouse Position Changes to Master Position
  179. moveMouse( m_mouseEvents[ index ].pos.x,
  180. m_mouseEvents[ index ].pos.y,
  181. movementType );
  182. // Cumulate Wheel Adjustments
  183. m_currMouse.wheelPos += m_mouseEvents[ index ].wheelPos;
  184. // Check Left Mouse State
  185. if( m_mouseEvents[ index ].leftFrame )
  186. {
  187. if( m_currMouse.leftState != m_mouseEvents[ index ].leftState )
  188. {
  189. // State Change
  190. if( m_mouseEvents[ index ].leftState == MBS_Down )
  191. {
  192. // Mouse Down
  193. m_currMouse.leftEvent = GWM_LEFT_DOWN;
  194. m_currMouse.leftState = MBS_Down;
  195. m_currMouse.leftFrame = m_inputFrame;
  196. }
  197. else if ( m_mouseEvents[ index ].leftState == MBS_DoubleClick )
  198. {
  199. // Mouse Double Click
  200. m_currMouse.leftEvent = GWM_LEFT_DOUBLE_CLICK;
  201. m_currMouse.leftState = MBS_DoubleClick;
  202. m_currMouse.leftFrame = m_inputFrame;
  203. }
  204. else
  205. {
  206. // Mouse Up
  207. m_currMouse.leftEvent = GWM_LEFT_UP;
  208. m_currMouse.leftState = MBS_Up;
  209. m_currMouse.leftFrame = m_inputFrame;
  210. }
  211. }
  212. }
  213. else if( m_currMouse.leftState != MBS_Up &&
  214. ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
  215. (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
  216. {
  217. m_currMouse.leftEvent = GWM_LEFT_DRAG;
  218. }
  219. // Check Right Mouse State
  220. if( m_mouseEvents[ index ].rightFrame )
  221. {
  222. if( m_currMouse.rightState != m_mouseEvents[ index ].rightState )
  223. {
  224. // State Change
  225. if( m_mouseEvents[ index ].rightState == MBS_Down )
  226. {
  227. // Mouse Down
  228. m_currMouse.rightEvent = GWM_RIGHT_DOWN;
  229. m_currMouse.rightState = MBS_Down;
  230. m_currMouse.rightFrame = m_inputFrame;
  231. }
  232. else if( m_mouseEvents[ index ].rightState == MBS_DoubleClick )
  233. {
  234. // Mouse Double Click
  235. m_currMouse.rightEvent = GWM_RIGHT_DOUBLE_CLICK;
  236. m_currMouse.rightState = MBS_DoubleClick;
  237. m_currMouse.rightFrame = m_inputFrame;
  238. }
  239. else
  240. {
  241. // Mouse Up
  242. m_currMouse.rightEvent = GWM_RIGHT_UP;
  243. m_currMouse.rightState = MBS_Up;
  244. m_currMouse.rightFrame = m_inputFrame;
  245. }
  246. }
  247. }
  248. else if( m_currMouse.rightState != MBS_Up &&
  249. ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
  250. (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
  251. {
  252. m_currMouse.rightEvent = GWM_RIGHT_DRAG;
  253. }
  254. // Check Middle Mouse State
  255. if( m_mouseEvents[ index ].middleFrame )
  256. {
  257. if( m_currMouse.middleState != m_mouseEvents[index].middleState )
  258. {
  259. // State Change
  260. if( m_mouseEvents[index].middleState == MBS_Down )
  261. {
  262. m_currMouse.middleEvent = GWM_MIDDLE_DOWN;
  263. m_currMouse.middleState = MBS_Down;
  264. m_currMouse.middleFrame = m_inputFrame;
  265. }
  266. else if( m_mouseEvents[index].middleState == MBS_DoubleClick )
  267. {
  268. m_currMouse.middleEvent = GWM_MIDDLE_DOUBLE_CLICK;
  269. m_currMouse.middleState = MBS_DoubleClick;
  270. m_currMouse.middleFrame = m_inputFrame;
  271. }
  272. else
  273. {
  274. // Mouse Up
  275. m_currMouse.middleEvent = GWM_MIDDLE_UP;
  276. m_currMouse.middleState = MBS_Up;
  277. m_currMouse.middleFrame = m_inputFrame;
  278. }
  279. }
  280. }
  281. else if( m_currMouse.middleState != MBS_Up &&
  282. ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
  283. (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
  284. {
  285. m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
  286. }
  287. m_currMouse.deltaPos.x = m_currMouse.pos.x - m_prevMouse.pos.x;
  288. m_currMouse.deltaPos.y = m_currMouse.pos.y - m_prevMouse.pos.y;
  289. // DEBUG_LOG(("Mouse dx %d, dy %d, index %d, frame %d\n", m_currMouse.deltaPos.x, m_currMouse.deltaPos.y, index, m_inputFrame));
  290. // // check if mouse is still and flag tooltip
  291. // if( ((dx*dx) + (dy*dy)) < CURSOR_MOVE_TOL_SQ )
  292. // {
  293. // // cursor is still
  294. // //m_stillTime++;
  295. // Int delay = m_tooltipDelayTime;
  296. // if(m_tooltipDelay >= 0 )
  297. // delay = m_tooltipDelay;
  298. //
  299. // if( now - m_stillTime >= delay )
  300. // {
  301. // if (!m_displayTooltip)
  302. // {
  303. // m_highlightPos = 0;
  304. // m_highlightUpdateStart = timeGetTime();
  305. // }
  306. //
  307. // // display tooltip for current window
  308. // m_displayTooltip = TRUE;
  309. // }
  310. // }
  311. // else
  312. // {
  313. // // cursor moved
  314. // //m_stillTime = 0;
  315. // m_stillTime = now;
  316. // m_displayTooltip = FALSE;
  317. // }
  318. m_prevMouse = m_currMouse;
  319. } // end processMouseEvent
  320. //-------------------------------------------------------------------------------------------------
  321. /** Check for mouse drag */
  322. //-------------------------------------------------------------------------------------------------
  323. void Mouse::checkForDrag( void )
  324. {
  325. if( m_currMouse.leftState &&
  326. ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
  327. (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
  328. {
  329. m_currMouse.leftEvent = GWM_LEFT_DRAG;
  330. }
  331. if( m_currMouse.rightState &&
  332. ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
  333. (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
  334. {
  335. m_currMouse.rightEvent = GWM_RIGHT_DRAG;
  336. }
  337. if( m_currMouse.middleState &&
  338. ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
  339. (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
  340. {
  341. m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
  342. }
  343. } // end checkForDrag
  344. //-------------------------------------------------------------------------------------------------
  345. /** Check for mouse click, using allowed drag forgiveness */
  346. //-------------------------------------------------------------------------------------------------
  347. Bool Mouse::isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick)
  348. {
  349. ICoord2D delta;
  350. delta.x = anchor->x - dest->x;
  351. delta.y = anchor->y - dest->y;
  352. // if the mouse hasn't moved further than the tolerance distance
  353. // or the click took less than the tolerance duration
  354. if ( abs(delta.x) > m_dragTolerance
  355. || abs(delta.y) > m_dragTolerance
  356. || currentMouseClick - previousMouseClick > m_dragToleranceMS)
  357. {
  358. return FALSE;
  359. }
  360. return TRUE;
  361. }
  362. ///////////////////////////////////////////////////////////////////////////////////////////////////
  363. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
  364. ///////////////////////////////////////////////////////////////////////////////////////////////////
  365. //-------------------------------------------------------------------------------------------------
  366. //-------------------------------------------------------------------------------------------------
  367. CursorInfo::CursorInfo( void )
  368. {
  369. // Added Sadullah Nader
  370. // Initializations missing and needed
  371. cursorName.clear();
  372. cursorText.clear();
  373. cursorTextColor.red = cursorTextColor.green = cursorTextColor.blue = 0;
  374. cursorTextDropColor.red = cursorTextDropColor.blue = cursorTextDropColor.green = 0;
  375. //
  376. textureName.clear();
  377. imageName.clear();
  378. W3DModelName.clear();
  379. W3DAnimName.clear();
  380. W3DScale = 1.0f;
  381. loop = TRUE;
  382. //Assume hotspot is at the center of a 32x32 image.
  383. hotSpotPosition.x=16;
  384. hotSpotPosition.y=16;
  385. numFrames = 1; //assume no animation
  386. fps=20.0f;
  387. numDirections=1;
  388. }
  389. //-------------------------------------------------------------------------------------------------
  390. //-------------------------------------------------------------------------------------------------
  391. Mouse::Mouse( void )
  392. {
  393. // device info
  394. m_numButtons = 0;
  395. m_numAxes = 0;
  396. m_forceFeedback = FALSE;
  397. //Added By Sadullah Nader
  398. //Initializations missing and needed
  399. m_dragTolerance = 0;
  400. m_dragTolerance3D = 0;
  401. m_dragToleranceMS = 0;
  402. //
  403. //m_tooltipString.clear(); // redundant
  404. m_displayTooltip = FALSE;
  405. m_tooltipDisplayString = NULL;
  406. m_tooltipDelay = -1; // default value
  407. // initialize all the mouse io data
  408. memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
  409. memset( &m_currMouse, 0, sizeof( m_currMouse ) );
  410. memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
  411. m_minX = 0;
  412. m_maxX = 0;
  413. m_minY = 0;
  414. m_maxY = 0;
  415. m_eventsThisFrame = 0;
  416. m_inputFrame = 0;
  417. m_deadInputFrame =0;
  418. m_inputMovesAbsolute = FALSE;
  419. m_currentCursor = ARROW;
  420. if (TheGlobalData && TheGlobalData->m_winCursors)
  421. m_currentRedrawMode = RM_WINDOWS;
  422. else
  423. m_currentRedrawMode = RM_W3D;//RM_WINDOWS;
  424. m_visible = FALSE;
  425. m_tooltipFontName = "Times New Roman";
  426. m_tooltipFontSize = 12;
  427. m_tooltipFontIsBold = FALSE;
  428. m_tooltipAnimateBackground = TRUE;
  429. m_tooltipFillTime = 50;
  430. m_tooltipDelayTime = 50;
  431. #define setColor(x, r, g, b, a) { x.red = r; x.green = g; x.blue = b; x.alpha = a; }
  432. setColor(m_tooltipColorText, 220, 220, 220, 255);
  433. setColor(m_tooltipColorHighlight, 255, 255, 0, 255);
  434. setColor(m_tooltipColorShadow, 0, 0, 0, 255);
  435. setColor(m_tooltipColorBackground, 20, 20, 0, 127);
  436. setColor(m_tooltipColorBorder, 0, 0, 0, 255);
  437. #undef setColor
  438. m_tooltipWidth = 15.0f;
  439. m_lastTooltipWidth = 0.0f;
  440. m_useTooltipAltTextColor = FALSE;
  441. m_useTooltipAltBackColor = FALSE;
  442. m_adjustTooltipAltColor = FALSE;
  443. m_orthoCamera = FALSE;
  444. m_orthoZoom = 1.0f;
  445. m_isTooltipEmpty = TRUE;
  446. m_cursorTextDisplayString = NULL;
  447. m_cursorTextColor.red = 255;
  448. m_cursorTextColor.green = 255;
  449. m_cursorTextColor.blue = 255;
  450. m_cursorTextColor.alpha = 255;
  451. m_cursorTextDropColor.red = 255;
  452. m_cursorTextDropColor.green = 255;
  453. m_cursorTextDropColor.blue = 255;
  454. m_cursorTextDropColor.alpha = 255;
  455. m_highlightPos = 0;
  456. m_highlightUpdateStart = 0;
  457. m_stillTime = 0;
  458. m_tooltipTextColor.red = 255;
  459. m_tooltipTextColor.green = 255;
  460. m_tooltipTextColor.blue = 255;
  461. m_tooltipTextColor.alpha = 255;
  462. m_tooltipBackColor.red = 0;
  463. m_tooltipBackColor.green = 0;
  464. m_tooltipBackColor.blue = 0;
  465. m_tooltipBackColor.alpha = 255;
  466. } // end Mouse
  467. //-------------------------------------------------------------------------------------------------
  468. //-------------------------------------------------------------------------------------------------
  469. Mouse::~Mouse( void )
  470. {
  471. if(m_tooltipDisplayString)
  472. TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
  473. m_tooltipDisplayString = NULL;
  474. if( m_cursorTextDisplayString )
  475. TheDisplayStringManager->freeDisplayString( m_cursorTextDisplayString );
  476. m_cursorTextDisplayString = NULL;
  477. } // end ~Mouse
  478. /**Had to move this out of main init() because I need this data to properly initialize
  479. the Win32 version of the mouse (by preloading resources before D3D device is created).*/
  480. void Mouse::parseIni(void)
  481. {
  482. INI ini;
  483. ini.load( AsciiString( "Data\\INI\\Mouse.ini" ), INI_LOAD_OVERWRITE, NULL );
  484. }
  485. //-------------------------------------------------------------------------------------------------
  486. /** Initialize the mouse */
  487. //-------------------------------------------------------------------------------------------------
  488. void Mouse::init( void )
  489. {
  490. if (TheGlobalData && TheGlobalData->m_winCursors)
  491. m_currentRedrawMode = RM_WINDOWS;
  492. // device info
  493. m_numButtons = 2; // by default just have 2 buttons
  494. m_numAxes = 2; // by default a normal mouse moves in a 2d plane
  495. m_forceFeedback = FALSE;
  496. mouseNotifyResolutionChange();
  497. m_tooltipString.clear(); // redundant
  498. m_displayTooltip = FALSE;
  499. // initialize all the mouse io data
  500. memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
  501. memset( &m_currMouse, 0, sizeof( m_currMouse ) );
  502. memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
  503. m_minX = 0;
  504. m_maxX = 799;
  505. m_minY = 0;
  506. m_maxY = 599;
  507. m_inputFrame = 0;
  508. m_deadInputFrame =0;
  509. m_inputMovesAbsolute = FALSE;
  510. m_eventsThisFrame = 0;
  511. m_currentCursor = ARROW;
  512. // allocate a new display string
  513. m_cursorTextDisplayString = TheDisplayStringManager->newDisplayString();
  514. } // end init
  515. //-------------------------------------------------------------------------------------------------
  516. /** Tell mouse system display resolution changed. */
  517. //-------------------------------------------------------------------------------------------------
  518. void Mouse::mouseNotifyResolutionChange( void )
  519. {
  520. if(m_tooltipDisplayString)
  521. TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
  522. m_tooltipDisplayString = NULL;
  523. m_tooltipDisplayString = TheDisplayStringManager->newDisplayString();
  524. if (TheGlobalLanguageData && TheGlobalLanguageData->m_tooltipFontName.name.isNotEmpty())
  525. {
  526. m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
  527. TheGlobalLanguageData->m_tooltipFontName.name,
  528. TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_tooltipFontName.size),
  529. TheGlobalLanguageData->m_tooltipFontName.bold) );
  530. }
  531. else
  532. {
  533. m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
  534. m_tooltipFontName,
  535. TheGlobalLanguageData->adjustFontSize(m_tooltipFontSize),
  536. m_tooltipFontIsBold ) );
  537. }
  538. m_tooltipDisplayString->setWordWrap(120);
  539. } // end reset
  540. //-------------------------------------------------------------------------------------------------
  541. /** Reset mouse system */
  542. //-------------------------------------------------------------------------------------------------
  543. void Mouse::reset( void )
  544. {
  545. ///@ todo Write Mouse::reset() if there needs to be anything here
  546. // reset the text of the cursor text
  547. m_cursorTextDisplayString->reset();
  548. } // end reset
  549. //-------------------------------------------------------------------------------------------------
  550. /** Update the states of the mouse position and buttons */
  551. //-------------------------------------------------------------------------------------------------
  552. void Mouse::update( void )
  553. {
  554. // increment input frame
  555. m_inputFrame++;
  556. // update the mouse data
  557. updateMouseData( );
  558. } // end update
  559. //-------------------------------------------------------------------------------------------------
  560. /** Given the current state of this input device, turn the raw input
  561. * data into raw stream messages and place those messages on the stream.
  562. * NOTE that the click messages replace up messages in the mouse, so we
  563. * are going to propagate those click messages in addition to up messages */
  564. //-------------------------------------------------------------------------------------------------
  565. void Mouse::createStreamMessages( void )
  566. {
  567. // santiy
  568. if( TheMessageStream == NULL )
  569. return; // no place to put messages
  570. GameMessage *msg = NULL;
  571. UnsignedInt now = timeGetTime();
  572. // basic position messages are always created
  573. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_POSITION );
  574. msg->appendPixelArgument( m_currMouse.pos );
  575. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  576. Int delay = m_tooltipDelayTime;
  577. if(m_tooltipDelay >= 0 )
  578. delay = m_tooltipDelay;
  579. if( now - m_stillTime >= delay )
  580. {
  581. if (!m_displayTooltip)
  582. {
  583. m_highlightPos = 0;
  584. m_highlightUpdateStart = timeGetTime();
  585. }
  586. // display tooltip for current window
  587. m_displayTooltip = TRUE;
  588. }
  589. else
  590. {
  591. //DEBUG_LOG(("%d %d %d %d\n", TheGameClient->getFrame(), delay, now, m_stillTime));
  592. m_displayTooltip = FALSE;
  593. }
  594. for (Int i = 0; i < m_eventsThisFrame; ++i)
  595. {
  596. processMouseEvent(i);
  597. if (m_currMouse.deltaPos.x || m_currMouse.deltaPos.y)
  598. m_stillTime = now;
  599. // button messages
  600. msg = NULL;
  601. switch( m_currMouse.leftEvent )
  602. {
  603. case GWM_LEFT_DOWN:
  604. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN );
  605. msg->appendPixelArgument( m_currMouse.pos );
  606. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  607. msg->appendIntegerArgument( m_currMouse.time );
  608. break;
  609. case GWM_LEFT_DOUBLE_CLICK:
  610. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK );
  611. msg->appendPixelArgument( m_currMouse.pos );
  612. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  613. msg->appendIntegerArgument( m_currMouse.time );
  614. break;
  615. case GWM_LEFT_UP:
  616. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP );
  617. msg->appendPixelArgument( m_currMouse.pos );
  618. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  619. msg->appendIntegerArgument( m_currMouse.time );
  620. break;
  621. case GWM_LEFT_DRAG:
  622. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DRAG );
  623. msg->appendPixelArgument( m_currMouse.pos );
  624. msg->appendPixelArgument( m_currMouse.deltaPos );
  625. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  626. break;
  627. } // end switch
  628. msg = NULL;
  629. switch( m_currMouse.middleEvent )
  630. {
  631. //-------------------------------------------------------------------------
  632. case GWM_MIDDLE_DOWN:
  633. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN );
  634. msg->appendPixelArgument( m_currMouse.pos );
  635. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  636. msg->appendIntegerArgument( m_currMouse.time );
  637. break;
  638. case GWM_MIDDLE_DOUBLE_CLICK:
  639. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK );
  640. msg->appendPixelArgument( m_currMouse.pos );
  641. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  642. msg->appendIntegerArgument( m_currMouse.time );
  643. break;
  644. case GWM_MIDDLE_UP:
  645. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP );
  646. msg->appendPixelArgument( m_currMouse.pos );
  647. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  648. msg->appendIntegerArgument( m_currMouse.time );
  649. break;
  650. case GWM_MIDDLE_DRAG:
  651. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG );
  652. msg->appendPixelArgument( m_currMouse.pos );
  653. msg->appendPixelArgument( m_currMouse.deltaPos );
  654. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  655. break;
  656. } // end switch
  657. msg = NULL;
  658. switch( m_currMouse.rightEvent )
  659. {
  660. //-------------------------------------------------------------------------
  661. case GWM_RIGHT_DOWN:
  662. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN );
  663. msg->appendPixelArgument( m_currMouse.pos );
  664. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  665. msg->appendIntegerArgument( m_currMouse.time );
  666. break;
  667. case GWM_RIGHT_DOUBLE_CLICK:
  668. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK );
  669. msg->appendPixelArgument( m_currMouse.pos );
  670. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  671. msg->appendIntegerArgument( m_currMouse.time );
  672. break;
  673. case GWM_RIGHT_UP:
  674. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP );
  675. msg->appendPixelArgument( m_currMouse.pos );
  676. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  677. msg->appendIntegerArgument( m_currMouse.time );
  678. break;
  679. case GWM_RIGHT_DRAG:
  680. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG );
  681. msg->appendPixelArgument( m_currMouse.pos );
  682. msg->appendPixelArgument( m_currMouse.deltaPos );
  683. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  684. break;
  685. } // end switch
  686. // wheel pos
  687. msg = NULL;
  688. if( m_currMouse.wheelPos != 0 )
  689. {
  690. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL );
  691. msg->appendPixelArgument( m_currMouse.pos );
  692. msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta
  693. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  694. } // end if
  695. } // end for
  696. } // end createStreamMessages
  697. //-------------------------------------------------------------------------------------------------
  698. /** Set the string to display at the cursor for the tooltip */
  699. //-------------------------------------------------------------------------------------------------
  700. void Mouse::setCursorTooltip( UnicodeString tooltip, Int delay, const RGBColor *color, Real width )
  701. {
  702. //DEBUG_LOG(("%d Tooltip: %ls\n", TheGameClient->getFrame(), tooltip.str()));
  703. m_isTooltipEmpty = tooltip.isEmpty();
  704. m_tooltipDelay = delay;
  705. Bool forceRecalc = FALSE;
  706. if ( !tooltip.isEmpty() && width != m_lastTooltipWidth )
  707. {
  708. forceRecalc = TRUE;
  709. Int widthInPixels = (Int)(TheDisplay->getWidth()*m_tooltipWidth*width);
  710. if (widthInPixels < 10)
  711. {
  712. widthInPixels = 120;
  713. }
  714. else if (widthInPixels > TheDisplay->getWidth())
  715. {
  716. widthInPixels = TheDisplay->getWidth();
  717. }
  718. //DEBUG_LOG(("Setting tooltip width to %d pixels (%g%% of the normal tooltip width)\n", widthInPixels, width*100));
  719. m_tooltipDisplayString->setWordWrap( widthInPixels );
  720. m_lastTooltipWidth = width;
  721. }
  722. if (forceRecalc || !m_isTooltipEmpty && tooltip.compare(m_tooltipDisplayString->getText()))
  723. {
  724. m_tooltipDisplayString->setText(tooltip);
  725. //DEBUG_LOG(("Tooltip: %ls\n", tooltip.str()));
  726. }
  727. if (color)
  728. {
  729. if (m_useTooltipAltTextColor)
  730. {
  731. if (m_adjustTooltipAltColor)
  732. {
  733. m_tooltipTextColor.red = REAL_TO_INT((color->red + 1.0f) * 255.0f / 2.0f);
  734. m_tooltipTextColor.green = REAL_TO_INT((color->green + 1.0f) * 255.0f / 2.0f);
  735. m_tooltipTextColor.blue = REAL_TO_INT((color->blue + 1.0f) * 255.0f / 2.0f);
  736. }
  737. else
  738. {
  739. m_tooltipTextColor.red = REAL_TO_INT(color->red * 255.0f);
  740. m_tooltipTextColor.green = REAL_TO_INT(color->green * 255.0f);
  741. m_tooltipTextColor.blue = REAL_TO_INT(color->blue * 255.0f);
  742. }
  743. m_tooltipTextColor.alpha = m_tooltipColorText.alpha;
  744. }
  745. if (m_useTooltipAltBackColor)
  746. {
  747. if (m_adjustTooltipAltColor)
  748. {
  749. m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f * 0.5f);
  750. m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f * 0.5f);
  751. m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f * 0.5f);
  752. }
  753. else
  754. {
  755. m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f);
  756. m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f);
  757. m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f);
  758. }
  759. m_tooltipBackColor.alpha = m_tooltipColorBackground.alpha;
  760. }
  761. }
  762. else
  763. {
  764. m_tooltipTextColor = m_tooltipColorText;
  765. m_tooltipBackColor = m_tooltipColorBackground;
  766. }
  767. } // end setCursorTooltip
  768. // ------------------------------------------------------------------------------------------------
  769. /** Set the text for the mouse cursor ... note that this is *NOT* the tooltip text we
  770. * can set to be at the mouse position */
  771. // ------------------------------------------------------------------------------------------------
  772. void Mouse::setMouseText( UnicodeString text,
  773. const RGBAColorInt *color,
  774. const RGBAColorInt *dropColor )
  775. {
  776. // sanity, if no display string has been created, get out of here
  777. if( m_cursorTextDisplayString == NULL )
  778. return;
  779. // set the text into the cursor display string
  780. m_cursorTextDisplayString->setText( text );
  781. // save the colors to draw in
  782. if( color )
  783. m_cursorTextColor = *color;
  784. if( dropColor )
  785. m_cursorTextDropColor = *dropColor;
  786. } // end setMouseText
  787. //-------------------------------------------------------------------------------------------------
  788. /** Move the mouse to the position */
  789. //-------------------------------------------------------------------------------------------------
  790. void Mouse::setPosition( Int x, Int y )
  791. {
  792. m_currMouse.pos.x = x;
  793. m_currMouse.pos.y = y;
  794. } // end setPosition
  795. //-------------------------------------------------------------------------------------------------
  796. /** This default implemtation of SetMouseLimits will just set the limiting
  797. * rectangle to be the width and height of the game display with the
  798. * origin in the upper left at (0,0). However, if the game is running
  799. * in a windowed mode then these limits should reflect the SCREEN
  800. * coords that the mouse is allowed to move in. Also, if the game is in
  801. * a window you may want to adjust for any title bar available in
  802. * the operating system. For system specific limits and windows etc,
  803. * just override this function in the device implementation of the mouse */
  804. //-------------------------------------------------------------------------------------------------
  805. void Mouse::setMouseLimits( void )
  806. {
  807. m_minX = 0;
  808. m_minY = 0;
  809. if( TheDisplay )
  810. {
  811. m_maxX = TheDisplay->getWidth();
  812. m_maxY = TheDisplay->getHeight();
  813. } // end if
  814. } // end setMouseLimits
  815. //-------------------------------------------------------------------------------------------------
  816. /** Draw the mouse */
  817. //-------------------------------------------------------------------------------------------------
  818. void Mouse::draw( void )
  819. {
  820. }
  821. // ------------------------------------------------------------------------------------------------
  822. // ------------------------------------------------------------------------------------------------
  823. void Mouse::resetTooltipDelay( void )
  824. {
  825. m_stillTime = timeGetTime();
  826. m_displayTooltip = FALSE;
  827. }
  828. //-------------------------------------------------------------------------------------------------
  829. /** Draw the mouse tooltip if one is set */
  830. //-------------------------------------------------------------------------------------------------
  831. void Mouse::drawTooltip( void )
  832. {
  833. if (TheScriptEngine->getFade()!=ScriptEngine::FADE_NONE) {
  834. return;
  835. }
  836. /// @todo: Still need to put in display logic so it puts the tool tips in a visable position on the edge of the screen
  837. if( m_displayTooltip && TheDisplay && m_tooltipDisplayString && (m_tooltipDisplayString->getTextLength() > 0) && !m_isTooltipEmpty)
  838. {
  839. Int width, xPos;
  840. Int height, yPos;
  841. m_tooltipDisplayString->getSize(&width,&height);
  842. xPos = m_currMouse.pos.x + 20;
  843. yPos = m_currMouse.pos.y;// + 20;
  844. if( xPos + width + 4 > m_maxX ) // +4 for spill
  845. {
  846. //xPos = m_maxX - width;
  847. xPos -= 20 + width;
  848. }
  849. if( yPos + height + 4 > m_maxY ) // +4 for spill
  850. {
  851. //yPos = m_maxY - height;
  852. yPos -= /*40 +*/ height;
  853. }
  854. Int boxWidth = (m_tooltipAnimateBackground)?(min(width, m_highlightPos)):width;
  855. #define GMC(x) GameMakeColor(x.red, x.green, x.blue, x.alpha)
  856. #define COLOR(x) GMC(m_tooltipColor##x)
  857. TheDisplay->drawFillRect(xPos, yPos, boxWidth + 2,height + 2, GMC(m_tooltipBackColor));//GameMakeColor(0,0,0,125));
  858. TheDisplay->drawOpenRect(xPos, yPos, boxWidth + 2,height + 2, 1.0, COLOR(Border));//GameMakeColor(20,20,20,255));
  859. // build clip rect
  860. IRegion2D clipRegion;
  861. clipRegion.lo.x = xPos+2;
  862. clipRegion.lo.y = yPos+1;
  863. clipRegion.hi.x = xPos+2+m_highlightPos;
  864. clipRegion.hi.y = yPos+1+height;
  865. m_tooltipDisplayString->setClipRegion(&clipRegion);
  866. m_tooltipDisplayString->draw(xPos +2, yPos +1, GMC(m_tooltipTextColor), COLOR(Shadow));//GameMakeColor(220,220,220,255),GameMakeColor(20,20,20,125));
  867. // highlight section
  868. const Int HIGHLIGHT_WIDTH = 15;
  869. clipRegion.lo.x = xPos+2+m_highlightPos-HIGHLIGHT_WIDTH;
  870. clipRegion.lo.y = yPos+1;
  871. clipRegion.hi.x = xPos+2+m_highlightPos;
  872. clipRegion.hi.y = yPos+1+height;
  873. m_tooltipDisplayString->setClipRegion(&clipRegion);
  874. m_tooltipDisplayString->draw(xPos +2, yPos +1, COLOR(Highlight), COLOR(Shadow));//GameMakeColor(255,255,0,255),GameMakeColor(20,20,20,125));
  875. // get ready for the next part of the anim
  876. if (m_highlightPos < width + HIGHLIGHT_WIDTH)
  877. {
  878. UnsignedInt now = timeGetTime();
  879. m_highlightPos = (width*(now-m_highlightUpdateStart))/m_tooltipFillTime;
  880. }
  881. } // end if
  882. } // end drawTooltip
  883. // ------------------------------------------------------------------------------------------------
  884. /** Draw the cursor text at the mouse position. Note that this is *NOT* the tooltip text */
  885. // ------------------------------------------------------------------------------------------------
  886. void Mouse::drawCursorText( void )
  887. {
  888. // sanity
  889. if( m_cursorTextDisplayString == NULL )
  890. return;
  891. // get the colors to draw the text in an acceptable format
  892. Color color, dropColor;
  893. color = GameMakeColor( m_cursorTextColor.red,
  894. m_cursorTextColor.green,
  895. m_cursorTextColor.blue,
  896. m_cursorTextColor.alpha );
  897. dropColor = GameMakeColor( m_cursorTextDropColor.red,
  898. m_cursorTextDropColor.green,
  899. m_cursorTextDropColor.blue,
  900. m_cursorTextDropColor.alpha );
  901. // get the size of the text to draw
  902. Int width, height;
  903. m_cursorTextDisplayString->getSize( &width, &height );
  904. // draw the text around the cursor position
  905. Int x, y;
  906. x = m_currMouse.pos.x - width / 2;
  907. y = m_currMouse.pos.y - height / 2;
  908. m_cursorTextDisplayString->draw( x, y, color, dropColor );
  909. } // end drawCursorText
  910. // ------------------------------------------------------------------------------------------------
  911. // ------------------------------------------------------------------------------------------------
  912. Int Mouse::getCursorIndex(const AsciiString& name)
  913. {
  914. if (name.isEmpty())
  915. return INVALID_MOUSE_CURSOR;
  916. /** @todo This is silly to have to define these names from INI in the code ...
  917. * that should be changed (CBD) */
  918. static char *CursorININames[NUM_MOUSE_CURSORS] =
  919. {
  920. //"InvalidMouseCursor", // this entry is not actually a mouse cursor, but just a
  921. // reminder that it does exist
  922. "None",
  923. "Normal",
  924. "Arrow",
  925. "Scroll",
  926. "Target",
  927. "Move",
  928. "AttackMove",
  929. "AttackObj",
  930. "ForceAttackObj",
  931. "ForceAttackGround",
  932. "Build",
  933. "InvalidBuild",
  934. "GenericInvalid",
  935. "Select",
  936. "EnterFriendly",
  937. "EnterAggressive",
  938. "SetRallyPoint",
  939. "GetRepaired",
  940. "GetHealed",
  941. "DoRepair",
  942. "ResumeConstruction",
  943. "CaptureBuilding",
  944. "SnipeVehicle",
  945. "LaserGuidedMissiles",
  946. "TankHunterTNTAttack",
  947. "StabAttack",
  948. "PlaceRemoteCharge",
  949. "PlaceTimedCharge",
  950. "Defector",
  951. #ifdef ALLOW_DEMORALIZE
  952. "Demoralize",
  953. #endif
  954. "Dock",
  955. #ifdef ALLOW_SURRENDER
  956. "PickUpPrisoner",
  957. "ReturnToPrison",
  958. #endif
  959. "FireFlame",
  960. #ifdef ALLOW_SURRENDER
  961. "FireTranqDarts",
  962. "FireStunBullets",
  963. #endif
  964. "FireBomb",
  965. "PlaceBeacon",
  966. "DisguiseAsVehicle",
  967. "Waypoint",
  968. "OutRange",
  969. "StabAttackInvalid",
  970. "PlaceChargeInvalid",
  971. "Hack",
  972. "ParticleUplinkCannon",
  973. };
  974. for (Int i=0; i<NUM_MOUSE_CURSORS; ++i)
  975. {
  976. if (name.compareNoCase(CursorININames[i]) == 0)
  977. return i;
  978. }
  979. DEBUG_CRASH(( "Mouse::getCursorIndex - Invalid cursor name '%s'\n", name.str() ));
  980. return INVALID_MOUSE_CURSOR;
  981. }
  982. // ------------------------------------------------------------------------------------------------
  983. // ------------------------------------------------------------------------------------------------
  984. void Mouse::setCursor( MouseCursor cursor )
  985. {
  986. // if cursor has not changed do nothing
  987. if( m_currentCursor == cursor )
  988. return;
  989. // only if we have a display cursor do we do anything with mouse text
  990. if( m_cursorTextDisplayString != NULL )
  991. {
  992. CursorInfo *cursorInfo = &m_cursorInfo[ cursor ];
  993. //
  994. // if there is text present into the cursor info, set it into the mouse, otherwise
  995. // just clear out the text for the cursor text
  996. //
  997. if( cursorInfo->cursorText.isEmpty() == FALSE )
  998. setMouseText( TheGameText->fetch( cursorInfo->cursorText.str() ),
  999. &(cursorInfo->cursorTextColor),
  1000. &(cursorInfo->cursorTextDropColor) );
  1001. else
  1002. setMouseText( UnicodeString( L"" ), NULL, NULL );
  1003. } // end if
  1004. } // end setCursor
  1005. //-------------------------------------------------------------------------------------------------
  1006. /** Parse MouseCursor entry */
  1007. //-------------------------------------------------------------------------------------------------
  1008. void INI::parseMouseCursorDefinition( INI* ini )
  1009. {
  1010. const char *c;
  1011. AsciiString name;
  1012. // read the name
  1013. c = ini->getNextToken();
  1014. name.set( c );
  1015. if( TheMouse )
  1016. {
  1017. Int index = TheMouse->getCursorIndex(name);
  1018. if (index != Mouse::INVALID_MOUSE_CURSOR)
  1019. {
  1020. CursorInfo *cursorInfo = &(TheMouse->m_cursorInfo[index]);
  1021. cursorInfo->cursorName = name;
  1022. // parse the ini weapon definition
  1023. ini->initFromINI( cursorInfo, TheMouseCursorFieldParseTable );
  1024. }
  1025. }
  1026. }
  1027. //-------------------------------------------------------------------------------------------------
  1028. /** Parse MouseCursor entry */
  1029. //-------------------------------------------------------------------------------------------------
  1030. void INI::parseMouseDefinition( INI* ini )
  1031. {
  1032. if( TheMouse )
  1033. {
  1034. // parse the ini weapon definition
  1035. ini->initFromINI( TheMouse, TheMouseFieldParseTable );
  1036. }
  1037. }