wwmouse.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /*
  2. ** Command & Conquer Renegade(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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/Library/wwmouse.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 8/11/97 10:14a $*
  29. * *
  30. * $Revision:: 2 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * Callback_Process_Mouse -- Mouse O/S callback function. *
  35. * WWMouseClass::WWMouseClass -- Constructor for mouse handler object. *
  36. * WWMouseClass::~WWMouseClass -- Destructor for mouse handler object. *
  37. * WWMouseClass::Get_Mouse_State -- Fetch the current mouse visibility state. *
  38. * WWMouseClass::Set_Cursor -- Set the mouse cursor shape. *
  39. * WWMouseClass::Is_Data_Valid -- Determines if there is valid shape image data. *
  40. * WWMouseClass::Validate_Copy_Buffer -- Checks for and validates the background copy buffer.*
  41. * WWMouseClass::Matching_Rect -- Finds rectangle of current cursor position & size. *
  42. * WWMouseClass::Save_Background -- Saves the background to a copy buffer. *
  43. * WWMouseClass::Restore_Background -- Restores the image back where it came from. *
  44. * WWMouseClass::Draw_Mouse -- Manually draw the mouse to the surface specified. *
  45. * WWMouseClass::Erase_Mouse -- Restores the surface after a Draw_Mouse call. *
  46. * WWMouseClass::Raw_Draw_Mouse -- Draws the mouse to the surface specified. *
  47. * WWMouseClass::Low_Show_Mouse -- Shows the mouse and saves the background. *
  48. * WWMouseClass::Low_Hide_Mouse -- Restores the surface image in order to hide the mouse. *
  49. * WWMouseClass::Show_Mouse -- Shows the mouse on the visible surface. *
  50. * WWMouseClass::Hide_Mouse -- Hides the mouse from the visible surface. *
  51. * WWMouseClass::Capture_Mouse -- Capture the mouse into the mouse handler region. *
  52. * WWMouseClass::Release_Mouse -- Release the mouse back to the O/S. *
  53. * WWMouseClass::Conditional_Hide_Mouse -- Hides the mouse if it would overlap the region spe*
  54. * WWMouseClass::Conditional_Show_Mouse -- Releases the mouse hiding region tracking. *
  55. * WWMouseClass::Convert_Coordinate -- Convert an O/S coordinate into a logical coordinate. *
  56. * WWMouseClass::Get_Bounded_Position -- Fetches the mouse position from the O/S. *
  57. * WWMouseClass::Update_Mouse_Position -- Updates the mouse position to match that specified.*
  58. * WWMouseClass::Process_Mouse -- Mouse processing callback routine. *
  59. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  60. #include "always.h"
  61. #include "_convert.h"
  62. #include "_mono.h"
  63. #include "blit.h"
  64. #include "bsurface.h"
  65. #include "draw.h"
  66. #include "shapeset.h"
  67. #include "surface.h"
  68. #include "win.h"
  69. #include "wwmouse.h"
  70. #include <assert.h>
  71. /*
  72. ** Persistant mouse object pointer that is used to facilitate access to the mouse
  73. ** handler object outside of the context of a member function. This will be set to the
  74. ** mouse object most recently created.
  75. */
  76. static WWMouseClass * _MousePtr = NULL;
  77. /***********************************************************************************************
  78. * Callback_Process_Mouse -- Mouse O/S callback function. *
  79. * *
  80. * This routine is called periodically by the operating system. It handles updating the *
  81. * mouse cursor position to match the mouse movement. *
  82. * *
  83. * INPUT: n/a *
  84. * *
  85. * OUTPUT: none *
  86. * *
  87. * WARNINGS: none *
  88. * *
  89. * HISTORY: *
  90. * 03/10/1997 JLB : Created. *
  91. *=============================================================================================*/
  92. void CALLBACK Callback_Process_Mouse( UINT, UINT, DWORD, DWORD, DWORD )
  93. {
  94. if (_MousePtr != NULL) {
  95. _MousePtr->Process_Mouse();
  96. }
  97. }
  98. /***********************************************************************************************
  99. * WWMouseClass::WWMouseClass -- Constructor for mouse handler object. *
  100. * *
  101. * This is the constructor for the mouse handler object. It is assigned to a surface and *
  102. * given a confining rectangle. The mouse begins in a non-captured state. *
  103. * *
  104. * INPUT: surfaceptr -- Pointer to the visible display surface that will show the mouse. *
  105. * *
  106. * confine -- The confining rectangle within the visible surface. The mouse *
  107. * coordinates are bound to this rectangle. *
  108. * *
  109. * OUTPUT: none *
  110. * *
  111. * WARNINGS: none *
  112. * *
  113. * HISTORY: *
  114. * 03/10/1997 JLB : Created. *
  115. *=============================================================================================*/
  116. WWMouseClass::WWMouseClass(Surface * surfaceptr, HWND window) :
  117. Blocked(false),
  118. MouseState(-1),
  119. IsCaptured(false),
  120. MouseX(0),
  121. MouseY(0),
  122. SurfacePtr(surfaceptr),
  123. Window(window),
  124. MouseShape(NULL),
  125. ShapeNumber(0),
  126. MouseXHot(0),
  127. MouseYHot(0),
  128. Background(NULL),
  129. Alternate(NULL),
  130. SidebarAlternate(NULL),
  131. ConditionalRect(0,0,0,0),
  132. ConditionalState(-1),
  133. TimerHandle(0)
  134. {
  135. _MousePtr = this;
  136. TimerHandle = timeSetEvent(1000/60, 1, Callback_Process_Mouse, 0, TIME_PERIODIC);
  137. Calc_Confining_Rect();
  138. MouseXHot = ConfiningRect.X + (ConfiningRect.Width/2);
  139. MouseYHot = ConfiningRect.Y + (ConfiningRect.Height/2);
  140. }
  141. /***********************************************************************************************
  142. * WWMouseClass::~WWMouseClass -- Destructor for mouse handler object. *
  143. * *
  144. * This will remove the mouse handler object from being processed. It returns the mouse *
  145. * back to O/S control. *
  146. * *
  147. * INPUT: none *
  148. * *
  149. * OUTPUT: none *
  150. * *
  151. * WARNINGS: none *
  152. * *
  153. * HISTORY: *
  154. * 03/10/1997 JLB : Created. *
  155. *=============================================================================================*/
  156. WWMouseClass::~WWMouseClass(void)
  157. {
  158. if (TimerHandle != 0) {
  159. timeKillEvent(TimerHandle);
  160. _MousePtr = NULL;
  161. }
  162. delete Background;
  163. Background = NULL;
  164. delete Alternate;
  165. Alternate = NULL;
  166. delete SidebarAlternate;
  167. SidebarAlternate = NULL;
  168. }
  169. void WWMouseClass::Calc_Confining_Rect(void)
  170. {
  171. RECT rect;
  172. GetClientRect(Window, &rect);
  173. POINT point;
  174. point.x = rect.left;
  175. point.y = rect.top;
  176. ClientToScreen(Window, &point);
  177. POINT lr;
  178. lr.x = rect.right;
  179. lr.y = rect.bottom;
  180. ClientToScreen(Window, &lr);
  181. ConfiningRect = Rect(point.x, point.y, lr.x-point.x, lr.y-point.y);
  182. // ConfiningRect = Rect(point.x, point.y, lr.x-point.x+1, lr.y-point.y+1);
  183. }
  184. /***********************************************************************************************
  185. * WWMouseClass::Get_Mouse_State -- Fetch the current mouse visibility state. *
  186. * *
  187. * This routine is used to retrieve the current mouse state as it relates to visiblity. *
  188. * By using this routine it is possible to determine if the mouse is visible. *
  189. * *
  190. * INPUT: none *
  191. * *
  192. * OUTPUT: Returns with the current mouse visibility state. If the return value is less than *
  193. * 0 (i.e., negative), then the mouse is hidden. *
  194. * *
  195. * WARNINGS: none *
  196. * *
  197. * HISTORY: *
  198. * 03/10/1997 JLB : Created. *
  199. *=============================================================================================*/
  200. int WWMouseClass::Get_Mouse_State(void) const
  201. {
  202. if (!Is_Captured()) {
  203. ShowCursor(FALSE);
  204. int state = ShowCursor(TRUE);
  205. return(state);
  206. }
  207. return(MouseState);
  208. }
  209. /***********************************************************************************************
  210. * WWMouseClass::Set_Cursor -- Set the mouse cursor shape. *
  211. * *
  212. * This routine sets the mouse cursor image and hot-spot. The shape only applies to the *
  213. * mouse when it is captured (the normal case). Repeated calls to this routine is used *
  214. * to give the mouse animation. *
  215. * *
  216. * INPUT: xhotspot, yhotspot -- The X,Y offset from the upper left corner of the shape *
  217. * that specifies the hot-spot of the image. Positive values *
  218. * are right and down from the upper left corner. *
  219. * *
  220. * cursor -- Pointer to the shape data. *
  221. * *
  222. * shape -- The shape number to use within the shape data set specified. *
  223. * *
  224. * OUTPUT: none *
  225. * *
  226. * WARNINGS: none *
  227. * *
  228. * HISTORY: *
  229. * 03/10/1997 JLB : Created. *
  230. *=============================================================================================*/
  231. void WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, ShapeSet const * cursor, int shape)
  232. {
  233. if (cursor != NULL) {
  234. if (Is_Captured()) {
  235. Block_Mouse();
  236. if (!Is_Hidden()) Low_Hide_Mouse();
  237. MouseShape = cursor;
  238. ShapeNumber = shape;
  239. MouseXHot = xhotspot;
  240. MouseYHot = yhotspot;
  241. if (!Is_Hidden()) Low_Show_Mouse();
  242. Unblock_Mouse();
  243. } else {
  244. MouseShape = cursor;
  245. ShapeNumber = shape;
  246. MouseXHot = xhotspot;
  247. MouseYHot = yhotspot;
  248. }
  249. }
  250. }
  251. /***********************************************************************************************
  252. * WWMouseClass::Is_Data_Valid -- Determines if there is valid shape image data. *
  253. * *
  254. * This routine does a simple check to determine if the shape handler has been supplied *
  255. * a pointer to shape imagery. Any internal routine that requires the data to be present *
  256. * should call this routine to be sure it actually is. *
  257. * *
  258. * INPUT: none *
  259. * *
  260. * OUTPUT: bool; Has a shape image data pointer been supplied to this mouse handler? *
  261. * *
  262. * WARNINGS: When the mouse object is first created, no image data has been assigned. The *
  263. * Set_Cursor must be called before this routine will return TRUE. *
  264. * *
  265. * HISTORY: *
  266. * 03/10/1997 JLB : Created. *
  267. *=============================================================================================*/
  268. bool WWMouseClass::Is_Data_Valid(void) const
  269. {
  270. if (MouseShape != NULL) {
  271. return(true);
  272. }
  273. return(false);
  274. }
  275. /***********************************************************************************************
  276. * WWMouseClass::Validate_Copy_Buffer -- Checks for and validates the background copy buffer. *
  277. * *
  278. * This routine checks and allocates if necessary a buffer that is big enough to hold the *
  279. * background image under the mouse. Whenever the background buffer is needed, this routine *
  280. * should be called to ensure that it is valid. *
  281. * *
  282. * INPUT: none *
  283. * *
  284. * OUTPUT: bool; Is the buffer valid? *
  285. * *
  286. * WARNINGS: This routine might fail if there was insufficient memory. *
  287. * *
  288. * HISTORY: *
  289. * 03/10/1997 JLB : Created. *
  290. *=============================================================================================*/
  291. bool WWMouseClass::Validate_Copy_Buffer(void)
  292. {
  293. if (Is_Data_Valid()) {
  294. /*
  295. ** If there is a background buffer already allocated, then verify that
  296. ** it is large enough for the current shape data. If not, then free the
  297. ** buffer and reallocate it at the larger size.
  298. */
  299. if (Background != NULL) {
  300. if (MouseShape->Get_Width() > Background->Get_Width() ||
  301. MouseShape->Get_Height() > Background->Get_Height()) {
  302. delete Background;
  303. Background = NULL;
  304. }
  305. }
  306. if (Alternate != NULL) {
  307. if (MouseShape->Get_Width() > Alternate->Get_Width() ||
  308. MouseShape->Get_Height() > Alternate->Get_Height()) {
  309. delete Alternate;
  310. Alternate = NULL;
  311. }
  312. }
  313. if (SidebarAlternate != NULL) {
  314. if (MouseShape->Get_Width() > SidebarAlternate->Get_Width() ||
  315. MouseShape->Get_Height() > SidebarAlternate->Get_Height()) {
  316. delete SidebarAlternate;
  317. SidebarAlternate = NULL;
  318. }
  319. }
  320. /*
  321. ** Allocate a new background buffer if necessary. This must be big enough to
  322. ** hold the largest sized shape from the currently assigned shape set data.
  323. */
  324. if (Background == NULL) {
  325. Background = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
  326. }
  327. if (Alternate == NULL) {
  328. Alternate = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
  329. }
  330. if (SidebarAlternate == NULL) {
  331. SidebarAlternate = new BSurface(MouseShape->Get_Width(), MouseShape->Get_Height(), SurfacePtr->Bytes_Per_Pixel());
  332. }
  333. return(Background != NULL && Alternate != NULL && SidebarAlternate != NULL);
  334. }
  335. return(false);
  336. }
  337. /***********************************************************************************************
  338. * WWMouseClass::Matching_Rect -- Finds rectangle of current cursor position & size. *
  339. * *
  340. * This routine will return the logical rectangle that exactly encloses the cursor. This *
  341. * routine is typically used when drawing the cursor and manipulating the background buffer *
  342. * under it. *
  343. * *
  344. * INPUT: none *
  345. * *
  346. * OUTPUT: Returns with the rectangle that surrounds the cursor. *
  347. * *
  348. * WARNINGS: The rectangle is in logical coordinates. It may have to be biased to O/S *
  349. * coordinates if necessary. *
  350. * *
  351. * HISTORY: *
  352. * 03/10/1997 JLB : Created. *
  353. *=============================================================================================*/
  354. Rect WWMouseClass::Matching_Rect(void) const
  355. {
  356. Rect rect;
  357. if (Is_Data_Valid()) {
  358. ((WWMouseClass *)this)->Block_Mouse();
  359. /*
  360. ** Build the rectangle that the mouse shape will consume.
  361. */
  362. rect = MouseShape->Get_Rect(ShapeNumber);
  363. rect.X += MouseX - MouseXHot;
  364. rect.Y += MouseY - MouseYHot;
  365. ((WWMouseClass *)this)->Unblock_Mouse();
  366. }
  367. return(rect);
  368. }
  369. /***********************************************************************************************
  370. * WWMouseClass::Save_Background -- Saves the background to a copy buffer. *
  371. * *
  372. * This routine will save the region under the mouse (or where the mouse would appear at) *
  373. * to a copy buffer. *
  374. * *
  375. * INPUT: none *
  376. * *
  377. * OUTPUT: none *
  378. * *
  379. * WARNINGS: The previous contents of the copy buffer will be overwritten by this routine. *
  380. * *
  381. * HISTORY: *
  382. * 03/10/1997 JLB : Created. *
  383. *=============================================================================================*/
  384. void WWMouseClass::Save_Background(void)
  385. {
  386. if (Validate_Copy_Buffer()) {
  387. /*
  388. ** Build the rectangle that the mouse shape will consume.
  389. */
  390. SavedRegion = Matching_Rect();
  391. Rect rect = SavedRegion;
  392. rect.X += ConfiningRect.X;
  393. rect.Y += ConfiningRect.Y;
  394. /*
  395. ** Blit the background from the surface to the holding buffer.
  396. */
  397. // Rect old = SurfacePtr->Get_Rect();
  398. // SurfacePtr->Window.Reset();
  399. Background->Blit_From(Rect(0, 0, rect.Width, rect.Height), *SurfacePtr, rect);
  400. // SurfacePtr->Window.Set(old);
  401. }
  402. }
  403. /***********************************************************************************************
  404. * WWMouseClass::Restore_Background -- Restores the image back where it came from. *
  405. * *
  406. * This is the counterpart routine to the Save_Background function. It will restore the *
  407. * image from the copy buffer back to the screen where it came from. *
  408. * *
  409. * INPUT: none *
  410. * *
  411. * OUTPUT: none *
  412. * *
  413. * WARNINGS: none *
  414. * *
  415. * HISTORY: *
  416. * 03/10/1997 JLB : Created. *
  417. *=============================================================================================*/
  418. void WWMouseClass::Restore_Background(void)
  419. {
  420. if (SavedRegion.Is_Valid()) {
  421. Rect rect = SavedRegion;
  422. rect.X += ConfiningRect.X;
  423. rect.Y += ConfiningRect.Y;
  424. /*
  425. ** Blit the background from the holding buffer to the surface.
  426. */
  427. // Rect old = SurfacePtr->Get_Rect();
  428. // SurfacePtr->Window.Reset();
  429. SurfacePtr->Blit_From(rect, *Background, Rect(0, 0, rect.Width, rect.Height));
  430. // SurfacePtr->Window.Set(old);
  431. }
  432. }
  433. /***********************************************************************************************
  434. * WWMouseClass::Draw_Mouse -- Manually draw the mouse to the surface specified. *
  435. * *
  436. * This is a kludge function that can be used to reduce mouse flicker. Normally the mouse *
  437. * must be hidden before an image is copied to the visible surface. By drawing the mouse *
  438. * in the correct position on the source image prior to the copy, the mouse doesn't need *
  439. * to be hidden and no mouse flicker occurs. This routine handles this manual draw process. *
  440. * *
  441. * INPUT: surface -- Pointer to the surface that the mouse will be drawn to. *
  442. * *
  443. * OUTPUT: none *
  444. * *
  445. * WARNINGS: The destination surface is presumed to be the exact dimensions of the bouding *
  446. * rectangle specified in the mouse constructor. The call to Erase_Mouse must *
  447. * occur as soon as possible since the mouse is frozen until it is called. *
  448. * *
  449. * HISTORY: *
  450. * 03/10/1997 JLB : Created. *
  451. *=============================================================================================*/
  452. void WWMouseClass::Draw_Mouse(Surface * surface, bool issidebarsurface)
  453. {
  454. BSurface *savesurface;
  455. Rect *savedregion;
  456. int xoffset;
  457. int yoffset;
  458. if (issidebarsurface){
  459. xoffset = -480;
  460. yoffset = 0;
  461. savesurface = SidebarAlternate;
  462. savedregion = &SidebarAltRegion;
  463. }else{
  464. xoffset = 0;
  465. yoffset = 0;
  466. savesurface = Alternate;
  467. savedregion = &AltRegion;
  468. }
  469. if (!Is_Hidden() && surface != NULL && surface != SurfacePtr && savesurface != NULL) {
  470. Block_Mouse();
  471. /*
  472. ** Blit the background from the surface to the holding buffer.
  473. */
  474. //Rect old = surface->Window.Get_Rect();
  475. //surface->Window.Reset();
  476. *savedregion = SavedRegion;
  477. savedregion->X += xoffset;
  478. savedregion->Y += yoffset;
  479. savesurface->Blit_From(Rect(0, 0, savedregion->Width, savedregion->Height), *surface, *savedregion);
  480. if (issidebarsurface){
  481. if (savedregion->X < 0 && -savedregion->X < Background->Get_Width()){
  482. Background->Blit_From(Rect(-savedregion->X, 0, savedregion->Width, savedregion->Height),
  483. *surface, Rect(0,savedregion->Y, savedregion->Width, savedregion->Height));
  484. }
  485. }else{
  486. Background->Blit_From(Rect(0, 0, savedregion->Width, savedregion->Height), *surface, *savedregion);
  487. }
  488. //surface->Window.Set(old);
  489. Raw_Draw_Mouse(surface, xoffset, yoffset);
  490. Unblock_Mouse();
  491. } else {
  492. savedregion->Width = 0;
  493. }
  494. }
  495. /***********************************************************************************************
  496. * WWMouseClass::Erase_Mouse -- Restores the surface after a Draw_Mouse call. *
  497. * *
  498. * This is the counterpart routine to Draw_Mouse. It will restore the specified surface *
  499. * back to its original state. The mouse is frozen between the calls to Draw_Mouse and *
  500. * Erase_Mouse, so it is imperative to call this routine at the first legal opportunity. *
  501. * *
  502. * INPUT: surface -- Pointer to the surface that the mouse was previously drawn to. *
  503. * *
  504. * OUTPUT: none *
  505. * *
  506. * WARNINGS: none *
  507. * *
  508. * HISTORY: *
  509. * 03/10/1997 JLB : Created. *
  510. *=============================================================================================*/
  511. void WWMouseClass::Erase_Mouse(Surface * surface, bool issidebarsurface)
  512. {
  513. if (!Is_Hidden() && surface != NULL && surface != SurfacePtr && Alternate != NULL && SidebarAlternate != NULL) {
  514. BSurface *savesurface;
  515. Rect savedregion;
  516. if (issidebarsurface){
  517. savesurface = SidebarAlternate;
  518. savedregion = SidebarAltRegion;
  519. }else{
  520. savesurface = Alternate;
  521. savedregion = AltRegion;
  522. }
  523. /*
  524. ** Blit the background from the holding buffer to the surface.
  525. */
  526. Block_Mouse();
  527. //Rect old = surface->Window.Get_Rect();
  528. //surface->Window.Reset();
  529. surface->Blit_From(savedregion, *savesurface, Rect(0, 0, savedregion.Width, savedregion.Height));
  530. //surface->Window.Set(old);
  531. Unblock_Mouse();
  532. }
  533. }
  534. /***********************************************************************************************
  535. * WWMouseClass::Raw_Draw_Mouse -- Draws the mouse to the surface specified. *
  536. * *
  537. * This will draw the mouse image to the surface specified. It does not do any checking *
  538. * except to make sure that the mouse image data is nominally valid. *
  539. * *
  540. * INPUT: surface -- The surface to draw the mouse upon. *
  541. * *
  542. * OUTPUT: none *
  543. * *
  544. * WARNINGS: The background is not preserved by this routine. *
  545. * *
  546. * HISTORY: *
  547. * 03/10/1997 JLB : Created. *
  548. *=============================================================================================*/
  549. void WWMouseClass::Raw_Draw_Mouse(Surface * surface, int xoffset, int yoffset)
  550. {
  551. if (Is_Data_Valid() && surface != NULL) {
  552. /*
  553. ** Determine the rectangle that the mouse will be drawn
  554. ** to.
  555. */
  556. Rect rect = SavedRegion;
  557. rect.X += xoffset;
  558. rect.Y += yoffset;
  559. // if (surface == SurfacePtr) {
  560. // rect.X += ConfiningRect.X;
  561. // rect.Y += ConfiningRect.Y;
  562. // }
  563. // Rect old = surface->Get_Rect();
  564. // surface->Window.Reset();
  565. BSurface mdata(rect.Width, rect.Height, 1, MouseShape->Get_Data(ShapeNumber));
  566. if (surface == SurfacePtr) {
  567. Blit_Block(*surface, *NormalDrawer, mdata, Rect(0, 0, rect.Width, rect.Height), Point2D(rect.X, rect.Y), ConfiningRect);
  568. } else {
  569. Blit_Block(*surface, *NormalDrawer, mdata, Rect(0, 0, rect.Width, rect.Height), Point2D(rect.X, rect.Y), surface->Get_Rect());
  570. }
  571. //surface->Window.Set(old);
  572. }
  573. }
  574. /***********************************************************************************************
  575. * WWMouseClass::Low_Show_Mouse -- Shows the mouse and saves the background. *
  576. * *
  577. * This routine will save the background and then draw the mouse to the visible surface. *
  578. * *
  579. * INPUT: none *
  580. * *
  581. * OUTPUT: none *
  582. * *
  583. * WARNINGS: none *
  584. * *
  585. * HISTORY: *
  586. * 03/10/1997 JLB : Created. *
  587. *=============================================================================================*/
  588. void WWMouseClass::Low_Show_Mouse(void)
  589. {
  590. Block_Mouse();
  591. Save_Background();
  592. Raw_Draw_Mouse(SurfacePtr, 0, 0);
  593. Unblock_Mouse();
  594. }
  595. /***********************************************************************************************
  596. * WWMouseClass::Low_Hide_Mouse -- Restores the surface image in order to hide the mouse. *
  597. * *
  598. * This routine will hide the mouse on the visible surface. It does this by restoring the *
  599. * pixels under where the mouse was previously drawn. *
  600. * *
  601. * INPUT: none *
  602. * *
  603. * OUTPUT: none *
  604. * *
  605. * WARNINGS: none *
  606. * *
  607. * HISTORY: *
  608. * 03/10/1997 JLB : Created. *
  609. *=============================================================================================*/
  610. void WWMouseClass::Low_Hide_Mouse(void)
  611. {
  612. Block_Mouse();
  613. Restore_Background();
  614. Unblock_Mouse();
  615. }
  616. /***********************************************************************************************
  617. * WWMouseClass::Show_Mouse -- Shows the mouse on the visible surface. *
  618. * *
  619. * This routine is called when the mouse can be shown on the visible surface. *
  620. * *
  621. * INPUT: none *
  622. * *
  623. * OUTPUT: none *
  624. * *
  625. * WARNINGS: none *
  626. * *
  627. * HISTORY: *
  628. * 03/10/1997 JLB : Created. *
  629. *=============================================================================================*/
  630. void WWMouseClass::Show_Mouse(void)
  631. {
  632. if (!Is_Captured()) {
  633. ShowCursor(TRUE);
  634. } else {
  635. Block_Mouse();
  636. InterlockedIncrement(&MouseState);
  637. if (MouseState == 0) {
  638. Low_Show_Mouse();
  639. }
  640. assert(MouseState != 1);
  641. if (MouseState > 0) MouseState = 0;
  642. Unblock_Mouse();
  643. }
  644. }
  645. /***********************************************************************************************
  646. * WWMouseClass::Hide_Mouse -- Hides the mouse from the visible surface. *
  647. * *
  648. * This routine is called when the mouse is desired to be hidden from the visible surface. *
  649. * Typically, this must occur if the pixels where the mouse is located will be accessed. *
  650. * *
  651. * INPUT: none *
  652. * *
  653. * OUTPUT: none *
  654. * *
  655. * WARNINGS: none *
  656. * *
  657. * HISTORY: *
  658. * 03/10/1997 JLB : Created. *
  659. *=============================================================================================*/
  660. void WWMouseClass::Hide_Mouse(void)
  661. {
  662. if (!Is_Captured()) {
  663. ShowCursor(FALSE);
  664. } else {
  665. Block_Mouse();
  666. InterlockedDecrement(&MouseState);
  667. if (MouseState == -1) {
  668. Low_Hide_Mouse();
  669. }
  670. Unblock_Mouse();
  671. }
  672. }
  673. /***********************************************************************************************
  674. * WWMouseClass::Capture_Mouse -- Capture the mouse into the mouse handler region. *
  675. * *
  676. * This routine will confine the mouse to the confining rectangle and take over drawing *
  677. * of the mouse image from the operating system. The typical state is to keep the mouse *
  678. * captured throughout the lifetime of the owning program. *
  679. * *
  680. * INPUT: none *
  681. * *
  682. * OUTPUT: none *
  683. * *
  684. * WARNINGS: none *
  685. * *
  686. * HISTORY: *
  687. * 03/10/1997 JLB : Created. *
  688. *=============================================================================================*/
  689. void WWMouseClass::Capture_Mouse(void)
  690. {
  691. if (this != NULL && !Is_Captured()) {
  692. Block_Mouse();
  693. while (ShowCursor(FALSE) > -1) {}
  694. while (ShowCursor(TRUE) < -1) {}
  695. Hide_Mouse();
  696. IsCaptured = true;
  697. Show_Mouse();
  698. Unblock_Mouse();
  699. }
  700. }
  701. /***********************************************************************************************
  702. * WWMouseClass::Release_Mouse -- Release the mouse back to the O/S. *
  703. * *
  704. * This is the counterpart routine to Capture_Mouse. This routine will return the drawing *
  705. * and movement controls back to the operating system. Although the mouse will probably *
  706. * be able to roam outside the confining rectangle, the coordinates returned by this class *
  707. * are clipped to the confining rectangle anyway. This gives the impression that the mouse *
  708. * is still at a legal position. The presumption is that the mouse needs to be released to *
  709. * the O/S for reasons outside of the game itself. As such, the shouldn't detect any *
  710. * illegal mouse position. *
  711. * *
  712. * INPUT: none *
  713. * *
  714. * OUTPUT: none *
  715. * *
  716. * WARNINGS: All mouse shape changes won't be relected while the mouse is released. The O/S *
  717. * handles drawing the mouse in that case. *
  718. * *
  719. * HISTORY: *
  720. * 03/10/1997 JLB : Created. *
  721. *=============================================================================================*/
  722. void WWMouseClass::Release_Mouse(void)
  723. {
  724. if (this != NULL && Is_Captured()) {
  725. Block_Mouse();
  726. Hide_Mouse();
  727. IsCaptured = false;
  728. while (ShowCursor(FALSE) > -1) {}
  729. while (ShowCursor(TRUE) < -1) {}
  730. Show_Mouse();
  731. Unblock_Mouse();
  732. }
  733. }
  734. /***********************************************************************************************
  735. * WWMouseClass::Conditional_Hide_Mouse -- Hides the mouse if it would overlap the region spec *
  736. * *
  737. * This routine will hide the mouse if it lies within the region specified or if it moves *
  738. * within the region. *
  739. * *
  740. * INPUT: rect -- The rectangle that the mouse should not be drawn within. *
  741. * *
  742. * OUTPUT: none *
  743. * *
  744. * WARNINGS: none *
  745. * *
  746. * HISTORY: *
  747. * 03/10/1997 JLB : Created. *
  748. *=============================================================================================*/
  749. void WWMouseClass::Conditional_Hide_Mouse(Rect )
  750. {
  751. Hide_Mouse();
  752. }
  753. /***********************************************************************************************
  754. * WWMouseClass::Conditional_Show_Mouse -- Releases the mouse hiding region tracking. *
  755. * *
  756. * This routine will release the region hiding tracking that was set up with a previous *
  757. * call to Conditional_Hide_Mouse(). *
  758. * *
  759. * INPUT: none *
  760. * *
  761. * OUTPUT: none *
  762. * *
  763. * WARNINGS: none *
  764. * *
  765. * HISTORY: *
  766. * 03/10/1997 JLB : Created. *
  767. *=============================================================================================*/
  768. void WWMouseClass::Conditional_Show_Mouse(void)
  769. {
  770. Show_Mouse();
  771. }
  772. /***********************************************************************************************
  773. * WWMouseClass::Convert_Coordinate -- Convert an O/S coordinate into a logical coordinate. *
  774. * *
  775. * Sometimes you come across system mouse coordinates and they need to be converted into *
  776. * game logical coordinates. This routine will perform this function. *
  777. * *
  778. * INPUT: x,y -- Reference to the coordinates that will be converted into game logical *
  779. * coordinates. *
  780. * *
  781. * OUTPUT: none *
  782. * *
  783. * WARNINGS: The coordinates will be bound as well as transformed by the confining rectangle.*
  784. * *
  785. * HISTORY: *
  786. * 03/10/1997 JLB : Created. *
  787. *=============================================================================================*/
  788. void WWMouseClass::Convert_Coordinate(int & x, int & y) const
  789. {
  790. /*
  791. ** Convert the mouse position to legal bounds.
  792. */
  793. x -= ConfiningRect.X;
  794. y -= ConfiningRect.Y;
  795. if (x < 0) x = 0;
  796. if (y < 0) y = 0;
  797. if (x >= ConfiningRect.Width) x = ConfiningRect.Width-1;
  798. if (y >= ConfiningRect.Height) y = ConfiningRect.Height-1;
  799. }
  800. /***********************************************************************************************
  801. * WWMouseClass::Get_Bounded_Position -- Fetches the mouse position from the O/S. *
  802. * *
  803. * Fetches the mouse coordinates from the O/S and converts them into logical coordinates. *
  804. * *
  805. * INPUT: x,y -- Reference to the coordinates that will be set by this routine. *
  806. * *
  807. * OUTPUT: none *
  808. * *
  809. * WARNINGS: none *
  810. * *
  811. * HISTORY: *
  812. * 03/10/1997 JLB : Created. *
  813. *=============================================================================================*/
  814. void WWMouseClass::Get_Bounded_Position(int & x, int & y) const
  815. {
  816. /*
  817. ** Get the mouse's current real cursor position
  818. */
  819. POINT pt;
  820. GetCursorPos(&pt); // get the current cursor position
  821. x = pt.x;
  822. y = pt.y;
  823. Convert_Coordinate(x, y);
  824. }
  825. /***********************************************************************************************
  826. * WWMouseClass::Update_Mouse_Position -- Updates the mouse position to match that specified. *
  827. * *
  828. * This routine will update the mouse to match the position speicifed. *
  829. * *
  830. * INPUT: x,y -- The coordinates to position the mouse (hot spot). The coordinates are *
  831. * specified as logical not O/S relative. *
  832. * *
  833. * OUTPUT: none *
  834. * *
  835. * WARNINGS: none *
  836. * *
  837. * HISTORY: *
  838. * 03/10/1997 JLB : Created. *
  839. *=============================================================================================*/
  840. void WWMouseClass::Update_Mouse_Position(int x, int y)
  841. {
  842. /*
  843. ** If the desired position is not the same as the current
  844. ** position, then hide the mouse, reposition it, then show
  845. ** the mouse.
  846. */
  847. Block_Mouse();
  848. if (x != MouseX || y != MouseY) {
  849. if (Is_Captured() && !Is_Hidden()) Low_Hide_Mouse();
  850. MouseX = x;
  851. MouseY = y;
  852. if (Is_Captured() && !Is_Hidden()) Low_Show_Mouse();
  853. }
  854. Unblock_Mouse();
  855. }
  856. /***********************************************************************************************
  857. * WWMouseClass::Process_Mouse -- Mouse processing callback routine. *
  858. * *
  859. * This routine should be called periodically (recommended 15 times per second). It will *
  860. * examine the operating system mouse position and then update the visible mouse to match. *
  861. * *
  862. * INPUT: none *
  863. * *
  864. * OUTPUT: none *
  865. * *
  866. * WARNINGS: none *
  867. * *
  868. * HISTORY: *
  869. * 03/10/1997 JLB : Created. *
  870. *=============================================================================================*/
  871. void WWMouseClass::Process_Mouse(void)
  872. {
  873. if (!Is_Blocked()) {
  874. Block_Mouse();
  875. /*
  876. ** Fetch and update the mouse position.
  877. */
  878. int x;
  879. int y;
  880. Get_Bounded_Position(x, y);
  881. Update_Mouse_Position(x, y);
  882. Unblock_Mouse();
  883. }
  884. }
  885. /***********************************************************************************************
  886. * WWMouseClass::Set_Mouse_XY -- Sets the cursor position *
  887. * *
  888. * This routine will convert the position passed into screen coordinates and tell Windows *
  889. * to position the mouse cursor there *
  890. * *
  891. * INPUT: x and y in game coordinates *
  892. * *
  893. * OUTPUT: none *
  894. * *
  895. * WARNINGS: none *
  896. * *
  897. * HISTORY: *
  898. * 08/11/1997 BG : Created. *
  899. *=============================================================================================*/
  900. void WWMouseClass::Set_Mouse_XY( int x, int y )
  901. {
  902. if (x < 0) x = 0; // clamp to game coordinates
  903. if (y < 0) y = 0;
  904. if (x >= ConfiningRect.Width) x = ConfiningRect.Width-1;
  905. if (y >= ConfiningRect.Height) y = ConfiningRect.Height-1;
  906. x += ConfiningRect.X; // convert to screen coordinates
  907. y += ConfiningRect.Y;
  908. SetCursorPos( x, y ); // set the current cursor position
  909. }