Mouse.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. if ( m_cursorTextDisplayString )
  548. m_cursorTextDisplayString->reset();
  549. } // end reset
  550. //-------------------------------------------------------------------------------------------------
  551. /** Update the states of the mouse position and buttons */
  552. //-------------------------------------------------------------------------------------------------
  553. void Mouse::update( void )
  554. {
  555. // increment input frame
  556. m_inputFrame++;
  557. // update the mouse data
  558. updateMouseData( );
  559. } // end update
  560. //-------------------------------------------------------------------------------------------------
  561. /** Given the current state of this input device, turn the raw input
  562. * data into raw stream messages and place those messages on the stream.
  563. * NOTE that the click messages replace up messages in the mouse, so we
  564. * are going to propagate those click messages in addition to up messages */
  565. //-------------------------------------------------------------------------------------------------
  566. void Mouse::createStreamMessages( void )
  567. {
  568. // santiy
  569. if( TheMessageStream == NULL )
  570. return; // no place to put messages
  571. GameMessage *msg = NULL;
  572. UnsignedInt now = timeGetTime();
  573. // basic position messages are always created
  574. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_POSITION );
  575. msg->appendPixelArgument( m_currMouse.pos );
  576. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  577. Int delay = m_tooltipDelayTime;
  578. if(m_tooltipDelay >= 0 )
  579. delay = m_tooltipDelay;
  580. if( TheGlobalData->m_scriptDebug )
  581. {
  582. //No delay while scriptdebugging!
  583. delay = 0;
  584. }
  585. if( now - m_stillTime >= delay )
  586. {
  587. if (!m_displayTooltip)
  588. {
  589. m_highlightPos = 0;
  590. m_highlightUpdateStart = timeGetTime();
  591. }
  592. // display tooltip for current window
  593. m_displayTooltip = TRUE;
  594. }
  595. else
  596. {
  597. //DEBUG_LOG(("%d %d %d %d\n", TheGameClient->getFrame(), delay, now, m_stillTime));
  598. m_displayTooltip = FALSE;
  599. }
  600. for (Int i = 0; i < m_eventsThisFrame; ++i)
  601. {
  602. processMouseEvent(i);
  603. if (m_currMouse.deltaPos.x || m_currMouse.deltaPos.y)
  604. m_stillTime = now;
  605. // button messages
  606. msg = NULL;
  607. switch( m_currMouse.leftEvent )
  608. {
  609. case GWM_LEFT_DOWN:
  610. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN );
  611. msg->appendPixelArgument( m_currMouse.pos );
  612. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  613. msg->appendIntegerArgument( m_currMouse.time );
  614. break;
  615. case GWM_LEFT_DOUBLE_CLICK:
  616. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK );
  617. msg->appendPixelArgument( m_currMouse.pos );
  618. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  619. msg->appendIntegerArgument( m_currMouse.time );
  620. break;
  621. case GWM_LEFT_UP:
  622. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP );
  623. msg->appendPixelArgument( m_currMouse.pos );
  624. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  625. msg->appendIntegerArgument( m_currMouse.time );
  626. break;
  627. case GWM_LEFT_DRAG:
  628. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DRAG );
  629. msg->appendPixelArgument( m_currMouse.pos );
  630. msg->appendPixelArgument( m_currMouse.deltaPos );
  631. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  632. break;
  633. } // end switch
  634. msg = NULL;
  635. switch( m_currMouse.middleEvent )
  636. {
  637. //-------------------------------------------------------------------------
  638. case GWM_MIDDLE_DOWN:
  639. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN );
  640. msg->appendPixelArgument( m_currMouse.pos );
  641. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  642. msg->appendIntegerArgument( m_currMouse.time );
  643. break;
  644. case GWM_MIDDLE_DOUBLE_CLICK:
  645. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK );
  646. msg->appendPixelArgument( m_currMouse.pos );
  647. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  648. msg->appendIntegerArgument( m_currMouse.time );
  649. break;
  650. case GWM_MIDDLE_UP:
  651. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP );
  652. msg->appendPixelArgument( m_currMouse.pos );
  653. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  654. msg->appendIntegerArgument( m_currMouse.time );
  655. break;
  656. case GWM_MIDDLE_DRAG:
  657. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG );
  658. msg->appendPixelArgument( m_currMouse.pos );
  659. msg->appendPixelArgument( m_currMouse.deltaPos );
  660. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  661. break;
  662. } // end switch
  663. msg = NULL;
  664. switch( m_currMouse.rightEvent )
  665. {
  666. //-------------------------------------------------------------------------
  667. case GWM_RIGHT_DOWN:
  668. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN );
  669. msg->appendPixelArgument( m_currMouse.pos );
  670. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  671. msg->appendIntegerArgument( m_currMouse.time );
  672. break;
  673. case GWM_RIGHT_DOUBLE_CLICK:
  674. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK );
  675. msg->appendPixelArgument( m_currMouse.pos );
  676. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  677. msg->appendIntegerArgument( m_currMouse.time );
  678. break;
  679. case GWM_RIGHT_UP:
  680. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP );
  681. msg->appendPixelArgument( m_currMouse.pos );
  682. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  683. msg->appendIntegerArgument( m_currMouse.time );
  684. break;
  685. case GWM_RIGHT_DRAG:
  686. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG );
  687. msg->appendPixelArgument( m_currMouse.pos );
  688. msg->appendPixelArgument( m_currMouse.deltaPos );
  689. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  690. break;
  691. } // end switch
  692. // wheel pos
  693. msg = NULL;
  694. if( m_currMouse.wheelPos != 0 )
  695. {
  696. msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL );
  697. msg->appendPixelArgument( m_currMouse.pos );
  698. msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta
  699. msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
  700. } // end if
  701. } // end for
  702. } // end createStreamMessages
  703. //-------------------------------------------------------------------------------------------------
  704. /** Set the string to display at the cursor for the tooltip */
  705. //-------------------------------------------------------------------------------------------------
  706. void Mouse::setCursorTooltip( UnicodeString tooltip, Int delay, const RGBColor *color, Real width )
  707. {
  708. //DEBUG_LOG(("%d Tooltip: %ls\n", TheGameClient->getFrame(), tooltip.str()));
  709. m_isTooltipEmpty = tooltip.isEmpty();
  710. m_tooltipDelay = delay;
  711. Bool forceRecalc = FALSE;
  712. if ( !tooltip.isEmpty() && width != m_lastTooltipWidth )
  713. {
  714. forceRecalc = TRUE;
  715. Int widthInPixels = (Int)(TheDisplay->getWidth()*m_tooltipWidth*width);
  716. if (widthInPixels < 10)
  717. {
  718. widthInPixels = 120;
  719. }
  720. else if (widthInPixels > TheDisplay->getWidth())
  721. {
  722. widthInPixels = TheDisplay->getWidth();
  723. }
  724. //DEBUG_LOG(("Setting tooltip width to %d pixels (%g%% of the normal tooltip width)\n", widthInPixels, width*100));
  725. m_tooltipDisplayString->setWordWrap( widthInPixels );
  726. m_lastTooltipWidth = width;
  727. }
  728. if (forceRecalc || !m_isTooltipEmpty && tooltip.compare(m_tooltipDisplayString->getText()))
  729. {
  730. m_tooltipDisplayString->setText(tooltip);
  731. //DEBUG_LOG(("Tooltip: %ls\n", tooltip.str()));
  732. }
  733. if (color)
  734. {
  735. if (m_useTooltipAltTextColor)
  736. {
  737. if (m_adjustTooltipAltColor)
  738. {
  739. m_tooltipTextColor.red = REAL_TO_INT((color->red + 1.0f) * 255.0f / 2.0f);
  740. m_tooltipTextColor.green = REAL_TO_INT((color->green + 1.0f) * 255.0f / 2.0f);
  741. m_tooltipTextColor.blue = REAL_TO_INT((color->blue + 1.0f) * 255.0f / 2.0f);
  742. }
  743. else
  744. {
  745. m_tooltipTextColor.red = REAL_TO_INT(color->red * 255.0f);
  746. m_tooltipTextColor.green = REAL_TO_INT(color->green * 255.0f);
  747. m_tooltipTextColor.blue = REAL_TO_INT(color->blue * 255.0f);
  748. }
  749. m_tooltipTextColor.alpha = m_tooltipColorText.alpha;
  750. }
  751. if (m_useTooltipAltBackColor)
  752. {
  753. if (m_adjustTooltipAltColor)
  754. {
  755. m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f * 0.5f);
  756. m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f * 0.5f);
  757. m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f * 0.5f);
  758. }
  759. else
  760. {
  761. m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f);
  762. m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f);
  763. m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f);
  764. }
  765. m_tooltipBackColor.alpha = m_tooltipColorBackground.alpha;
  766. }
  767. }
  768. else
  769. {
  770. m_tooltipTextColor = m_tooltipColorText;
  771. m_tooltipBackColor = m_tooltipColorBackground;
  772. }
  773. } // end setCursorTooltip
  774. // ------------------------------------------------------------------------------------------------
  775. /** Set the text for the mouse cursor ... note that this is *NOT* the tooltip text we
  776. * can set to be at the mouse position */
  777. // ------------------------------------------------------------------------------------------------
  778. void Mouse::setMouseText( UnicodeString text,
  779. const RGBAColorInt *color,
  780. const RGBAColorInt *dropColor )
  781. {
  782. // sanity, if no display string has been created, get out of here
  783. if( m_cursorTextDisplayString == NULL )
  784. return;
  785. // set the text into the cursor display string
  786. m_cursorTextDisplayString->setText( text );
  787. // save the colors to draw in
  788. if( color )
  789. m_cursorTextColor = *color;
  790. if( dropColor )
  791. m_cursorTextDropColor = *dropColor;
  792. } // end setMouseText
  793. //-------------------------------------------------------------------------------------------------
  794. /** Move the mouse to the position */
  795. //-------------------------------------------------------------------------------------------------
  796. void Mouse::setPosition( Int x, Int y )
  797. {
  798. m_currMouse.pos.x = x;
  799. m_currMouse.pos.y = y;
  800. } // end setPosition
  801. //-------------------------------------------------------------------------------------------------
  802. /** This default implemtation of SetMouseLimits will just set the limiting
  803. * rectangle to be the width and height of the game display with the
  804. * origin in the upper left at (0,0). However, if the game is running
  805. * in a windowed mode then these limits should reflect the SCREEN
  806. * coords that the mouse is allowed to move in. Also, if the game is in
  807. * a window you may want to adjust for any title bar available in
  808. * the operating system. For system specific limits and windows etc,
  809. * just override this function in the device implementation of the mouse */
  810. //-------------------------------------------------------------------------------------------------
  811. void Mouse::setMouseLimits( void )
  812. {
  813. m_minX = 0;
  814. m_minY = 0;
  815. if( TheDisplay )
  816. {
  817. m_maxX = TheDisplay->getWidth();
  818. m_maxY = TheDisplay->getHeight();
  819. } // end if
  820. } // end setMouseLimits
  821. //-------------------------------------------------------------------------------------------------
  822. /** Draw the mouse */
  823. //-------------------------------------------------------------------------------------------------
  824. void Mouse::draw( void )
  825. {
  826. }
  827. // ------------------------------------------------------------------------------------------------
  828. // ------------------------------------------------------------------------------------------------
  829. void Mouse::resetTooltipDelay( void )
  830. {
  831. m_stillTime = timeGetTime();
  832. m_displayTooltip = FALSE;
  833. }
  834. //-------------------------------------------------------------------------------------------------
  835. /** Draw the mouse tooltip if one is set */
  836. //-------------------------------------------------------------------------------------------------
  837. void Mouse::drawTooltip( void )
  838. {
  839. if (TheScriptEngine->getFade()!=ScriptEngine::FADE_NONE) {
  840. return;
  841. }
  842. /// @todo: Still need to put in display logic so it puts the tool tips in a visable position on the edge of the screen
  843. if( m_displayTooltip && TheDisplay && m_tooltipDisplayString && (m_tooltipDisplayString->getTextLength() > 0) && !m_isTooltipEmpty)
  844. {
  845. Int width, xPos;
  846. Int height, yPos;
  847. m_tooltipDisplayString->getSize(&width,&height);
  848. xPos = m_currMouse.pos.x + 20;
  849. yPos = m_currMouse.pos.y;// + 20;
  850. if( xPos + width + 4 > m_maxX ) // +4 for spill
  851. {
  852. //xPos = m_maxX - width;
  853. xPos -= 20 + width;
  854. }
  855. if( yPos + height + 4 > m_maxY ) // +4 for spill
  856. {
  857. //yPos = m_maxY - height;
  858. yPos -= /*40 +*/ height;
  859. }
  860. Int boxWidth = (m_tooltipAnimateBackground)?(min(width, m_highlightPos)):width;
  861. #define GMC(x) GameMakeColor(x.red, x.green, x.blue, x.alpha)
  862. #define COLOR(x) GMC(m_tooltipColor##x)
  863. TheDisplay->drawFillRect(xPos, yPos, boxWidth + 2,height + 2, GMC(m_tooltipBackColor));//GameMakeColor(0,0,0,125));
  864. TheDisplay->drawOpenRect(xPos, yPos, boxWidth + 2,height + 2, 1.0, COLOR(Border));//GameMakeColor(20,20,20,255));
  865. // build clip rect
  866. IRegion2D clipRegion;
  867. clipRegion.lo.x = xPos+2;
  868. clipRegion.lo.y = yPos+1;
  869. clipRegion.hi.x = xPos+2+m_highlightPos;
  870. clipRegion.hi.y = yPos+1+height;
  871. m_tooltipDisplayString->setClipRegion(&clipRegion);
  872. m_tooltipDisplayString->draw(xPos +2, yPos +1, GMC(m_tooltipTextColor), COLOR(Shadow));//GameMakeColor(220,220,220,255),GameMakeColor(20,20,20,125));
  873. // highlight section
  874. const Int HIGHLIGHT_WIDTH = 15;
  875. clipRegion.lo.x = xPos+2+m_highlightPos-HIGHLIGHT_WIDTH;
  876. clipRegion.lo.y = yPos+1;
  877. clipRegion.hi.x = xPos+2+m_highlightPos;
  878. clipRegion.hi.y = yPos+1+height;
  879. m_tooltipDisplayString->setClipRegion(&clipRegion);
  880. m_tooltipDisplayString->draw(xPos +2, yPos +1, COLOR(Highlight), COLOR(Shadow));//GameMakeColor(255,255,0,255),GameMakeColor(20,20,20,125));
  881. // get ready for the next part of the anim
  882. if (m_highlightPos < width + HIGHLIGHT_WIDTH)
  883. {
  884. UnsignedInt now = timeGetTime();
  885. m_highlightPos = (width*(now-m_highlightUpdateStart))/m_tooltipFillTime;
  886. }
  887. } // end if
  888. } // end drawTooltip
  889. // ------------------------------------------------------------------------------------------------
  890. /** Draw the cursor text at the mouse position. Note that this is *NOT* the tooltip text */
  891. // ------------------------------------------------------------------------------------------------
  892. void Mouse::drawCursorText( void )
  893. {
  894. // sanity
  895. if( m_cursorTextDisplayString == NULL )
  896. return;
  897. // get the colors to draw the text in an acceptable format
  898. Color color, dropColor;
  899. color = GameMakeColor( m_cursorTextColor.red,
  900. m_cursorTextColor.green,
  901. m_cursorTextColor.blue,
  902. m_cursorTextColor.alpha );
  903. dropColor = GameMakeColor( m_cursorTextDropColor.red,
  904. m_cursorTextDropColor.green,
  905. m_cursorTextDropColor.blue,
  906. m_cursorTextDropColor.alpha );
  907. // get the size of the text to draw
  908. Int width, height;
  909. m_cursorTextDisplayString->getSize( &width, &height );
  910. // draw the text around the cursor position
  911. Int x, y;
  912. x = m_currMouse.pos.x - width / 2;
  913. y = m_currMouse.pos.y - height / 2;
  914. m_cursorTextDisplayString->draw( x, y, color, dropColor );
  915. } // end drawCursorText
  916. // ------------------------------------------------------------------------------------------------
  917. // ------------------------------------------------------------------------------------------------
  918. Int Mouse::getCursorIndex(const AsciiString& name)
  919. {
  920. if (name.isEmpty())
  921. return INVALID_MOUSE_CURSOR;
  922. /** @todo This is silly to have to define these names from INI in the code ...
  923. * that should be changed (CBD) */
  924. static char *CursorININames[NUM_MOUSE_CURSORS] =
  925. {
  926. //"InvalidMouseCursor", // this entry is not actually a mouse cursor, but just a
  927. // reminder that it does exist
  928. "None",
  929. "Normal",
  930. "Arrow",
  931. "Scroll",
  932. "Target",
  933. "Move",
  934. "AttackMove",
  935. "AttackObj",
  936. "ForceAttackObj",
  937. "ForceAttackGround",
  938. "Build",
  939. "InvalidBuild",
  940. "GenericInvalid",
  941. "Select",
  942. "EnterFriendly",
  943. "EnterAggressive",
  944. "SetRallyPoint",
  945. "GetRepaired",
  946. "GetHealed",
  947. "DoRepair",
  948. "ResumeConstruction",
  949. "CaptureBuilding",
  950. "SnipeVehicle",
  951. "LaserGuidedMissiles",
  952. "TankHunterTNTAttack",
  953. "StabAttack",
  954. "PlaceRemoteCharge",
  955. "PlaceTimedCharge",
  956. "Defector",
  957. #ifdef ALLOW_DEMORALIZE
  958. "Demoralize",
  959. #endif
  960. "Dock",
  961. #ifdef ALLOW_SURRENDER
  962. "PickUpPrisoner",
  963. "ReturnToPrison",
  964. #endif
  965. "FireFlame",
  966. #ifdef ALLOW_SURRENDER
  967. "FireTranqDarts",
  968. "FireStunBullets",
  969. #endif
  970. "FireBomb",
  971. "PlaceBeacon",
  972. "DisguiseAsVehicle",
  973. "Waypoint",
  974. "OutRange",
  975. "StabAttackInvalid",
  976. "PlaceChargeInvalid",
  977. "Hack",
  978. "ParticleUplinkCannon",
  979. };
  980. for (Int i=0; i<NUM_MOUSE_CURSORS; ++i)
  981. {
  982. if (name.compareNoCase(CursorININames[i]) == 0)
  983. return i;
  984. }
  985. DEBUG_CRASH(( "Mouse::getCursorIndex - Invalid cursor name '%s'\n", name.str() ));
  986. return INVALID_MOUSE_CURSOR;
  987. }
  988. // ------------------------------------------------------------------------------------------------
  989. // ------------------------------------------------------------------------------------------------
  990. void Mouse::setCursor( MouseCursor cursor )
  991. {
  992. // if cursor has not changed do nothing
  993. if( m_currentCursor == cursor )
  994. return;
  995. // only if we have a display cursor do we do anything with mouse text
  996. if( m_cursorTextDisplayString != NULL )
  997. {
  998. CursorInfo *cursorInfo = &m_cursorInfo[ cursor ];
  999. //
  1000. // if there is text present into the cursor info, set it into the mouse, otherwise
  1001. // just clear out the text for the cursor text
  1002. //
  1003. if( cursorInfo->cursorText.isEmpty() == FALSE )
  1004. setMouseText( TheGameText->fetch( cursorInfo->cursorText.str() ),
  1005. &(cursorInfo->cursorTextColor),
  1006. &(cursorInfo->cursorTextDropColor) );
  1007. else
  1008. setMouseText( UnicodeString( L"" ), NULL, NULL );
  1009. } // end if
  1010. } // end setCursor
  1011. //-------------------------------------------------------------------------------------------------
  1012. /** Parse MouseCursor entry */
  1013. //-------------------------------------------------------------------------------------------------
  1014. void INI::parseMouseCursorDefinition( INI* ini )
  1015. {
  1016. const char *c;
  1017. AsciiString name;
  1018. // read the name
  1019. c = ini->getNextToken();
  1020. name.set( c );
  1021. if( TheMouse )
  1022. {
  1023. Int index = TheMouse->getCursorIndex(name);
  1024. if (index != Mouse::INVALID_MOUSE_CURSOR)
  1025. {
  1026. CursorInfo *cursorInfo = &(TheMouse->m_cursorInfo[index]);
  1027. cursorInfo->cursorName = name;
  1028. // parse the ini weapon definition
  1029. ini->initFromINI( cursorInfo, TheMouseCursorFieldParseTable );
  1030. }
  1031. }
  1032. }
  1033. //-------------------------------------------------------------------------------------------------
  1034. /** Parse MouseCursor entry */
  1035. //-------------------------------------------------------------------------------------------------
  1036. void INI::parseMouseDefinition( INI* ini )
  1037. {
  1038. if( TheMouse )
  1039. {
  1040. // parse the ini weapon definition
  1041. ini->initFromINI( TheMouse, TheMouseFieldParseTable );
  1042. }
  1043. }