GAUGE.CPP 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/GAUGE.CPP 1 3/03/97 10:24a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** 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 ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : GAUGE.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic, Maria del Mar McCready Legg *
  24. * *
  25. * Start Date : 01/15/95 *
  26. * *
  27. * Last Update : January 16, 1995 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * GaugeClass::Action -- Handles input events for the gauge. *
  32. * GaugeClass::Draw_Me -- Draws the body of the gauge. *
  33. * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value. *
  34. * GaugeClass::Set_Maximum -- Sets the maximum value for the gauge. *
  35. * GaugeClass::Set_Value -- Set the value of the gauge. *
  36. * GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset. *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #include "function.h"
  39. /***************************************************************************
  40. * GaugeClass::GaugeClass -- class constructor *
  41. * *
  42. * INPUT: id -- button ID *
  43. * *
  44. * x,y -- upper-left corner, in pixels *
  45. * *
  46. * w,h -- width, height, in pixels *
  47. * *
  48. * OUTPUT: none. *
  49. * *
  50. * WARNINGS: none. *
  51. * *
  52. * HISTORY: 01/05/1995 MML : Created. *
  53. *=========================================================================*/
  54. GaugeClass::GaugeClass(unsigned id, int x, int y, int w, int h)
  55. : ControlClass(id, x, y, w, h, LEFTHELD|LEFTPRESS|LEFTRELEASE, true)
  56. {
  57. Set_Maximum(255);
  58. Set_Value(0);
  59. HasThumb = true;
  60. IsHorizontal = (w > h);
  61. IsColorized = true;
  62. ClickDiff = 0;
  63. }
  64. /***********************************************************************************************
  65. * GaugeClass::Set_Maximum -- Sets the maximum value for the gauge. *
  66. * *
  67. * This routine will set the maximum value for the gauge. This is the largest value that *
  68. * the current setting may reach. The ability to change this allows the gauge to use and *
  69. * return values that are convenient for the programmer's current needs. *
  70. * *
  71. * INPUT: value -- The value to use as the gauge maximum. *
  72. * *
  73. * OUTPUT: bool; Was the gauge maximum changed? A false indicates that the specified value *
  74. * already matches the current maximum. *
  75. * *
  76. * WARNINGS: none *
  77. * *
  78. * HISTORY: *
  79. * 01/16/1995 JLB : Created. *
  80. *=============================================================================================*/
  81. int GaugeClass::Set_Maximum(int value)
  82. {
  83. if (value != MaxValue) {
  84. MaxValue = value;
  85. Flag_To_Redraw();
  86. return(true);
  87. }
  88. return(false);
  89. }
  90. /***********************************************************************************************
  91. * GaugeClass::Set_Value -- Set the value of the gauge. *
  92. * *
  93. * This routine will set the current value for the gauge. This value is clipped to the *
  94. * limits of the gauge maximum. *
  95. * *
  96. * INPUT: value -- The value to set at the new current value. *
  97. * *
  98. * OUTPUT: bool; Was the current setting changed? A false indicates that the setting *
  99. * specified is the same as what was already there. *
  100. * *
  101. * WARNINGS: none *
  102. * *
  103. * HISTORY: *
  104. * 01/16/1995 JLB : Created. *
  105. *=============================================================================================*/
  106. int GaugeClass::Set_Value(int value)
  107. {
  108. value = Bound(value, 0, MaxValue);
  109. if (value != CurValue) {
  110. CurValue = value;
  111. Flag_To_Redraw();
  112. return(true);
  113. }
  114. return(false);
  115. }
  116. /***********************************************************************************************
  117. * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value. *
  118. * *
  119. * Use this routine to convert the specified pixel offset into a gauge value. This is used *
  120. * in translating mouse clicks into a corresponding setting for the gauge. *
  121. * *
  122. * INPUT: pixel -- The pixel offset form the start of the gauge. *
  123. * *
  124. * OUTPUT: Returns with the setting value in gauge coordinates. *
  125. * *
  126. * WARNINGS: none *
  127. * *
  128. * HISTORY: *
  129. * 01/16/1995 JLB : Created. *
  130. *=============================================================================================*/
  131. int GaugeClass::Pixel_To_Value(int pixel)
  132. {
  133. int maximum;
  134. if (IsHorizontal) {
  135. pixel -= X+1;
  136. maximum = Width;
  137. } else {
  138. pixel -= Y+1;
  139. maximum = Height;
  140. }
  141. maximum -= 2;
  142. pixel = Bound(pixel, 0, maximum);
  143. return(MaxValue * fixed(pixel, maximum));
  144. // return(Fixed_To_Cardinal(MaxValue, Cardinal_To_Fixed(maximum, pixel)));
  145. }
  146. /***********************************************************************************************
  147. * GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset. *
  148. * *
  149. * Use this routine to convert the specified gauge value into a pixel offset from the *
  150. * star of the gauge. This is used for thumb positioning. *
  151. * *
  152. * INPUT: value -- The value to convert to a pixel offset. *
  153. * *
  154. * OUTPUT: Returns with the pixel offset of the specified value from the start of the *
  155. * gauge. *
  156. * *
  157. * WARNINGS: none *
  158. * *
  159. * HISTORY: *
  160. * 01/16/1995 JLB : Created. *
  161. *=============================================================================================*/
  162. int GaugeClass::Value_To_Pixel(int value)
  163. {
  164. int maximum;
  165. int start;
  166. if (IsHorizontal) {
  167. maximum = Width;
  168. start = X;
  169. } else {
  170. maximum = Height;
  171. start = Y;
  172. }
  173. maximum -= 2;
  174. return(start + maximum * fixed(value, MaxValue));
  175. // return(start + Fixed_To_Cardinal(maximum, Cardinal_To_Fixed(MaxValue, value)));
  176. }
  177. /***********************************************************************************************
  178. * GaugeClass::Draw_Me -- Draws the body of the gauge. *
  179. * *
  180. * This routine will draw the body of the gauge if necessary. *
  181. * *
  182. * INPUT: forced -- Should the gauge be redrawn regardless of the current redraw flag? *
  183. * *
  184. * OUTPUT: bool; Was the gauge redrawn? *
  185. * *
  186. * WARNINGS: none *
  187. * *
  188. * HISTORY: 01/16/1995 JLB : Created. *
  189. *=============================================================================================*/
  190. int GaugeClass::Draw_Me(int forced)
  191. {
  192. if (ControlClass::Draw_Me(forced)) {
  193. /*
  194. ** Hide the mouse
  195. */
  196. if (LogicPage == &SeenBuff) {
  197. Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
  198. }
  199. /*
  200. ** Draw the body & set text color
  201. */
  202. Draw_Box (X, Y, Width, Height, BOXSTYLE_DOWN, true);
  203. /*
  204. ** Colourize the inside of the gauge if indicated.
  205. */
  206. if (IsColorized) {
  207. int middle = Value_To_Pixel(CurValue);
  208. int color = GadgetClass::Get_Color_Scheme()->Bright;
  209. if (IsHorizontal) {
  210. if (middle >= (X + 1))
  211. LogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, color);
  212. } else {
  213. if (middle >= (Y + 1))
  214. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, color);
  215. }
  216. }
  217. if (HasThumb) {
  218. Draw_Thumb();
  219. }
  220. /*
  221. ** Display the mouse
  222. */
  223. if (LogicPage == &SeenBuff) {
  224. Conditional_Show_Mouse();
  225. }
  226. return(true);
  227. }
  228. return(false);
  229. }
  230. /***********************************************************************************************
  231. * GaugeClass::Action -- Handles input events for the gauge. *
  232. * *
  233. * This routine will handle input event processing for the gauge. It will adjust the *
  234. * current setting of the gauge according to the mouse position. *
  235. * *
  236. * INPUT: flags -- The input event that is the reason for this function call. *
  237. * key -- The key code that caused the event. *
  238. * *
  239. * OUTPUT: bool; Was the even recognized, processed, and no further gadget scanning is *
  240. * desired (for this pass). *
  241. * *
  242. * WARNINGS: none *
  243. * HISTORY: *
  244. * 01/16/1995 JLB : Created. *
  245. *=============================================================================================*/
  246. int GaugeClass::Action(unsigned flags, KeyNumType &key)
  247. {
  248. /*
  249. ** If there's no thumb on this gauge, it's a display-only device.
  250. */
  251. if (!HasThumb) {
  252. return(false);
  253. }
  254. /*
  255. ** We might end up clearing the event bits. Make sure that the sticky
  256. ** process is properly updated anyway.
  257. */
  258. Sticky_Process(flags);
  259. /*
  260. ** If the thumb is currently being "dragged around", then update the slider
  261. ** position according to the mouse position. In all other cases, ignore the
  262. ** button being held down.
  263. */
  264. if ((flags & LEFTPRESS) || ((flags & LEFTHELD) && StuckOn == this)) {
  265. /*
  266. ** Compute the difference between where we clicked, and the edge of
  267. ** the thumb (only if we clicked on the thumb.)
  268. */
  269. if (flags & LEFTPRESS) {
  270. int curpix = Value_To_Pixel(CurValue);
  271. int clickpix = (IsHorizontal ? Get_Mouse_X() : Get_Mouse_Y());
  272. if ( (clickpix > curpix) && (clickpix - curpix) < Thumb_Pixels()) {
  273. ClickDiff = (clickpix - curpix);
  274. } else {
  275. ClickDiff = 0;
  276. }
  277. int testval = Pixel_To_Value(IsHorizontal ?
  278. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);
  279. /*
  280. ** Correct for round-down errors in Pixel_To_Value() and
  281. ** Value_To_Pixel(); make ClickDiff exactly right so that
  282. ** at this point, Get_Mouse_n() - ClickDiff converts to
  283. ** CurValue.
  284. */
  285. while (testval < CurValue && ClickDiff > 0) {
  286. ClickDiff--;
  287. testval = Pixel_To_Value(IsHorizontal ?
  288. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);
  289. }
  290. }
  291. /*
  292. ** If no change occurred in the gauge, just call Control's Action routine,
  293. ** but turn off the flags so it won't fill in 'key' with the button ID.
  294. ** Thus, no button ID will be returned by Input.
  295. */
  296. if (!Set_Value(Pixel_To_Value(IsHorizontal ?
  297. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff))) {
  298. flags &= ~(LEFTHELD|LEFTRELEASE|LEFTPRESS);
  299. ControlClass::Action(0, key);
  300. key = KN_NONE;
  301. return(true);
  302. }
  303. } else {
  304. /*
  305. ** Ignore the left mouse button being held down if this gauge is not
  306. ** currently in "sticky" mode. This allows processing of the LEFTPRESS
  307. ** by any derived classes such that this gauge can be more closely
  308. ** controlled.
  309. */
  310. flags &= ~LEFTHELD;
  311. }
  312. return(ControlClass::Action(flags, key));
  313. }
  314. /***********************************************************************************************
  315. * GaugeClass::Draw_Thumb -- Draws the body of the gauge. *
  316. * *
  317. * This routine will draw the body of the gauge if necessary. *
  318. * *
  319. * INPUT: none. *
  320. * *
  321. * OUTPUT: none. *
  322. * *
  323. * WARNINGS: none. *
  324. * *
  325. * HISTORY: 01/16/1995 MML : Created. *
  326. *=============================================================================================*/
  327. void GaugeClass::Draw_Thumb(void)
  328. {
  329. int x = Value_To_Pixel(CurValue);
  330. if ((x + 4) > Value_To_Pixel(MaxValue)) {
  331. x = Value_To_Pixel(MaxValue) - 2;
  332. }
  333. if (x < X) {
  334. x = X;
  335. }
  336. if (IsHorizontal) {
  337. Draw_Box(x, Y, 4, Height, BOXSTYLE_RAISED, true);
  338. } else {
  339. Draw_Box(X, x, Width, 4, BOXSTYLE_RAISED, true);
  340. }
  341. }
  342. /***********************************************************************************************
  343. * TriColorGaugeClass::TriColorGaugeClass -- Constructor for 3 color (red\yellow\green) gauge. *
  344. * *
  345. * This routine will draw the body of the gauge if necessary. *
  346. * *
  347. * INPUT: See below. *
  348. * *
  349. * OUTPUT: none. *
  350. * *
  351. * WARNINGS: none. *
  352. * *
  353. * HISTORY: 01/16/1995 MML : Created. *
  354. *=============================================================================================*/
  355. TriColorGaugeClass::TriColorGaugeClass(unsigned id, int x, int y, int w, int h)
  356. : GaugeClass(id, x, y, w, h)
  357. {
  358. RedLimit = 0; // maximum value for red
  359. YellowLimit = 0; // maximum value for yellow
  360. }
  361. /***********************************************************************************************
  362. * TriColorGaugeClass::Set_Red_Limit -- Set the value for the red area of gauge. *
  363. * *
  364. * INPUT: int value. *
  365. * *
  366. * OUTPUT: bool true of false. *
  367. * *
  368. * WARNINGS: none. *
  369. * *
  370. * HISTORY: 01/16/1995 MML : Created. *
  371. *=============================================================================================*/
  372. int TriColorGaugeClass::Set_Red_Limit(int value)
  373. {
  374. if (value >= 0 && value < MaxValue) {
  375. // if (value > YellowLimit) {
  376. // RedLimit = YellowLimit;
  377. // YellowLimit = value;
  378. // } else {
  379. RedLimit = value;
  380. // }
  381. Flag_To_Redraw();
  382. return(true);
  383. }
  384. return(false);
  385. }
  386. /***********************************************************************************************
  387. * TriColorGaugeClass::Set_Yellow_Limit -- Set the value for the yellow area of gauge. *
  388. * *
  389. * INPUT: int value. *
  390. * *
  391. * OUTPUT: bool true of false. *
  392. * *
  393. * WARNINGS: none. *
  394. * *
  395. * HISTORY: 01/16/1995 MML : Created. *
  396. *=============================================================================================*/
  397. int TriColorGaugeClass::Set_Yellow_Limit(int value)
  398. {
  399. if (value >= 0 && value < MaxValue) {
  400. // if (value < RedLimit) {
  401. // YellowLimit = RedLimit;
  402. // RedLimit = value;
  403. // } else {
  404. YellowLimit = value;
  405. // }
  406. Flag_To_Redraw();
  407. return(true);
  408. }
  409. return(false);
  410. }
  411. /***********************************************************************************************
  412. * TriColorGaugeClass::Draw_Me -- Draw the tri color gauge. *
  413. * *
  414. * INPUT: int forced -- draw or not? *
  415. * *
  416. * OUTPUT: bool true of false. *
  417. * *
  418. * WARNINGS: none. *
  419. * *
  420. * HISTORY: 01/16/1995 MML : Created. *
  421. *=============================================================================================*/
  422. int TriColorGaugeClass::Draw_Me(int forced)
  423. {
  424. if (ControlClass::Draw_Me(forced)) {
  425. /*
  426. ** Hide the mouse
  427. */
  428. if (LogicPage == &SeenBuff) {
  429. Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
  430. }
  431. /*
  432. ** Draw the body & set text color
  433. */
  434. Draw_Box (X, Y, Width, Height, (IsDisabled ? BOXSTYLE_RAISED : BOXSTYLE_DOWN), true);
  435. /*
  436. ** Colourize the inside of the gauge if indicated.
  437. */
  438. int red = Value_To_Pixel(RedLimit);
  439. int yellow = Value_To_Pixel(YellowLimit);
  440. int middle = Value_To_Pixel(CurValue);
  441. if (CurValue <= RedLimit) {
  442. if (IsHorizontal) {
  443. LogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, PINK);
  444. } else {
  445. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, PINK);
  446. }
  447. } else if (CurValue > RedLimit && CurValue <= YellowLimit) {
  448. if (IsHorizontal) {
  449. LogicPage->Fill_Rect(X+1, Y+1, red, Y+Height-2, PINK);
  450. LogicPage->Fill_Rect(red, Y+1, middle, Y+Height-2, YELLOW);
  451. } else {
  452. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red, PINK);
  453. LogicPage->Fill_Rect(X+1, red, X+Width-2, middle, YELLOW);
  454. }
  455. } else if (CurValue > YellowLimit && CurValue <= MaxValue) {
  456. if (IsHorizontal) {
  457. LogicPage->Fill_Rect(X+1, Y+1, red, Y+Height-2, PINK);
  458. LogicPage->Fill_Rect(red, Y+1, yellow, Y+Height-2, YELLOW);
  459. LogicPage->Fill_Rect(yellow, Y+1, middle, Y+Height-2, GREEN);
  460. } else {
  461. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red, PINK);
  462. LogicPage->Fill_Rect(X+1, red, X+Width-2, yellow, YELLOW);
  463. LogicPage->Fill_Rect(X+1, yellow, X+Width-2, middle, GREEN);
  464. }
  465. }
  466. if (HasThumb) {
  467. Draw_Thumb();
  468. }
  469. /*
  470. ** Display the mouse
  471. */
  472. if (LogicPage == &SeenBuff) {
  473. Conditional_Show_Mouse();
  474. }
  475. return(true);
  476. }
  477. return(false);
  478. }