GAUGE.CPP 26 KB

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