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: F:\projects\c&c\vcs\code\gauge.cpv 2.19 16 Oct 1995 16:50:56 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::Value_To_Pixel -- Convert gauge value to pixel offset. *
  34. * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value. *
  35. * GaugeClass::Set_Value -- Set the value of the gauge. *
  36. * GaugeClass::Set_Maximum -- Sets the maximum value for the gauge. *
  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 guage 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. // value = MIN(value, MaxValue);
  110. // value = MAX(value, 0);
  111. if (value != CurValue) {
  112. CurValue = value;
  113. Flag_To_Redraw();
  114. return(true);
  115. }
  116. return(false);
  117. }
  118. /***********************************************************************************************
  119. * GaugeClass::Pixel_To_Value -- Convert a pixel offset into a gauge value. *
  120. * *
  121. * Use this routine to conver the specified pixel offset into a gauge value. This is used *
  122. * in translating mouse clicks into a cooresponding setting for the guage. *
  123. * *
  124. * INPUT: pixel -- The pixel offset form the start of the gauge. *
  125. * *
  126. * OUTPUT: Returns with the setting value in guage coordinates. *
  127. * *
  128. * WARNINGS: none *
  129. * *
  130. * HISTORY: *
  131. * 01/16/1995 JLB : Created. *
  132. *=============================================================================================*/
  133. int GaugeClass::Pixel_To_Value(int pixel)
  134. {
  135. int maximum;
  136. if (IsHorizontal) {
  137. pixel -= X+1;
  138. maximum = Width;
  139. } else {
  140. pixel -= Y+1;
  141. maximum = Height;
  142. }
  143. maximum -= 2;
  144. pixel = Bound(pixel, 0, maximum);
  145. // pixel = MIN(pixel, maximum);
  146. // pixel = MAX(pixel, 0);
  147. return(Fixed_To_Cardinal(MaxValue, Cardinal_To_Fixed(maximum, pixel)));
  148. }
  149. /***********************************************************************************************
  150. * GaugeClass::Value_To_Pixel -- Convert gauge value to pixel offset. *
  151. * *
  152. * Use this routine to convert the specified gauge value into a pixel offset from the *
  153. * star of the gauge. This is used for thumb positioning. *
  154. * *
  155. * INPUT: value -- The value to convert to a pixel offset. *
  156. * *
  157. * OUTPUT: Returns with the pixel offset of the specified value from the start of the *
  158. * guage. *
  159. * *
  160. * WARNINGS: none *
  161. * *
  162. * HISTORY: *
  163. * 01/16/1995 JLB : Created. *
  164. *=============================================================================================*/
  165. int GaugeClass::Value_To_Pixel(int value)
  166. {
  167. int maximum;
  168. int start;
  169. if (IsHorizontal) {
  170. maximum = Width;
  171. start = X;
  172. } else {
  173. maximum = Height;
  174. start = Y;
  175. }
  176. maximum -= 2;
  177. return(start + Fixed_To_Cardinal(maximum, Cardinal_To_Fixed(MaxValue, value)));
  178. }
  179. /***********************************************************************************************
  180. * GaugeClass::Draw_Me -- Draws the body of the gauge. *
  181. * *
  182. * This routine will draw the body of the gauge if necessary. *
  183. * *
  184. * INPUT: forced -- Should the gauge be redrawn regardless of the current redraw flag? *
  185. * *
  186. * OUTPUT: bool; Was the gauge redrawn? *
  187. * *
  188. * WARNINGS: none *
  189. * *
  190. * HISTORY: 01/16/1995 JLB : Created. *
  191. *=============================================================================================*/
  192. int GaugeClass::Draw_Me(int forced)
  193. {
  194. if (ControlClass::Draw_Me(forced)) {
  195. /*
  196. ===================== Hide the mouse =====================
  197. */
  198. if (LogicPage == &SeenBuff) {
  199. Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
  200. }
  201. /*
  202. =========== Draw the body & set text color ===============
  203. */
  204. Draw_Box (X, Y, Width, Height, BOXSTYLE_GREEN_DOWN, true);
  205. /*
  206. ** Colorize the inside of the gauge if indicated.
  207. */
  208. if (IsColorized) {
  209. int middle = Value_To_Pixel(CurValue);
  210. int color = CC_BRIGHT_GREEN;
  211. if (IsHorizontal) {
  212. if (middle >= (X + 1))
  213. LogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, color);
  214. } else {
  215. if (middle >= (Y + 1))
  216. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, color);
  217. }
  218. }
  219. if (HasThumb)
  220. Draw_Thumb();
  221. /*
  222. =================== Display the mouse ===================
  223. */
  224. if (LogicPage == &SeenBuff) {
  225. Conditional_Show_Mouse();
  226. }
  227. return(true);
  228. }
  229. return(false);
  230. }
  231. /***********************************************************************************************
  232. * GaugeClass::Action -- Handles input events for the gauge. *
  233. * *
  234. * This routine will handle input event processing for the gauge. It will adjust the *
  235. * current setting of the gauge according to the mouse position. *
  236. * *
  237. * INPUT: flags -- The input event that is the reason for this function call. *
  238. * key -- The key code that caused the event. *
  239. * *
  240. * OUTPUT: bool; Was the even recognized, processed, and no further gadget scanning is *
  241. * desird (for this pass). *
  242. * *
  243. * WARNINGS: none *
  244. * HISTORY: *
  245. * 01/16/1995 JLB : Created. *
  246. *=============================================================================================*/
  247. int GaugeClass::Action(unsigned flags, KeyNumType &key)
  248. {
  249. /*
  250. ** If there's no thumb on this gauge, it's a display-only device; ignore
  251. ** any input.
  252. */
  253. if (!HasThumb) {
  254. key = KN_NONE;
  255. return(true);
  256. }
  257. /*
  258. ** We might end up clearing the event bits. Make sure that the sticky
  259. ** process is properly updated anyway.
  260. */
  261. Sticky_Process(flags);
  262. /*
  263. ** If the thumb is currently being "dragged around", then update the slider
  264. ** position according to the mouse position. In all other cases, ignore the
  265. ** button being held down.
  266. */
  267. if ((flags & LEFTPRESS) || ((flags & LEFTHELD) && StuckOn == this)) {
  268. /*
  269. ** Compute the difference between where we clicked, and the edge of
  270. ** the thumb (only if we clicked on the thumb.)
  271. */
  272. if (flags & LEFTPRESS) {
  273. int curpix = Value_To_Pixel(CurValue);
  274. int clickpix = (IsHorizontal ? Get_Mouse_X() : Get_Mouse_Y());
  275. if ( (clickpix > curpix) && (clickpix - curpix) < Thumb_Pixels()) {
  276. ClickDiff = (clickpix - curpix);
  277. } else {
  278. ClickDiff = 0;
  279. }
  280. int testval = Pixel_To_Value(IsHorizontal ?
  281. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);
  282. /*
  283. ** Correct for round-down errors in Pixel_To_Value() and
  284. ** Value_To_Pixe(); make ClickDiff exactly right so that
  285. ** at this point, Get_Mouse_n() - ClickDiff converts to
  286. ** CurValue.
  287. */
  288. while (testval < CurValue && ClickDiff > 0) {
  289. ClickDiff--;
  290. testval = Pixel_To_Value(IsHorizontal ?
  291. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff);
  292. }
  293. }
  294. /*
  295. ** If no change occurred in the gauge, just call Control's Action routine,
  296. ** but turn off the flags so it won't fill in 'key' with the button ID.
  297. ** Thus, no button ID will be returned by Input.
  298. */
  299. if (!Set_Value(Pixel_To_Value(IsHorizontal ?
  300. Get_Mouse_X() - ClickDiff : Get_Mouse_Y() - ClickDiff))) {
  301. flags &= ~(LEFTHELD|LEFTRELEASE|LEFTPRESS);
  302. ControlClass::Action(0,key);
  303. key = KN_NONE;
  304. return(true);
  305. }
  306. } else {
  307. /*
  308. ** Ingore the left mouse button being held down if this gauge is not
  309. ** currently in "sticky" mode. This allows processing of the LEFTPRESS
  310. ** by any derived classes such that this guage can be more closely
  311. ** controlled.
  312. */
  313. flags &= ~LEFTHELD;
  314. }
  315. return(ControlClass::Action(flags, key));
  316. }
  317. /***********************************************************************************************
  318. * GaugeClass::Draw_Thumb -- Draws the body of the gauge. *
  319. * *
  320. * This routine will draw the body of the gauge if necessary. *
  321. * *
  322. * INPUT: none. *
  323. * *
  324. * OUTPUT: none. *
  325. * *
  326. * WARNINGS: none. *
  327. * *
  328. * HISTORY: 01/16/1995 MML : Created. *
  329. *=============================================================================================*/
  330. void GaugeClass::Draw_Thumb(void)
  331. {
  332. int x = Value_To_Pixel(CurValue);
  333. // if ((x + 8) > Value_To_Pixel(MaxValue)) {
  334. if ((x + 4) > Value_To_Pixel(MaxValue)) {
  335. x = Value_To_Pixel(MaxValue) - 2;
  336. }
  337. if (IsHorizontal) {
  338. Draw_Box(x, Y, 4, Height, BOXSTYLE_GREEN_RAISED, true);
  339. //Draw_Box(x, Y, 8, Height, BOXSTYLE_GREEN_RAISED, true);
  340. } else {
  341. Draw_Box(X, x, Width, 4, BOXSTYLE_GREEN_RAISED, true);
  342. //Draw_Box(X, x, Width, 8, BOXSTYLE_GREEN_RAISED, true);
  343. }
  344. }
  345. /***********************************************************************************************
  346. * TriColorGaugeClass::TriColorGaugeClass -- Constructor for 3 color (red\yellow\green) gauge. *
  347. * *
  348. * This routine will draw the body of the gauge if necessary. *
  349. * *
  350. * INPUT: See below. *
  351. * *
  352. * OUTPUT: none. *
  353. * *
  354. * WARNINGS: none. *
  355. * *
  356. * HISTORY: 01/16/1995 MML : Created. *
  357. *=============================================================================================*/
  358. TriColorGaugeClass::TriColorGaugeClass(unsigned id, int x, int y, int w, int h)
  359. : GaugeClass(id, x, y, w, h)
  360. {
  361. RedLimit = 0; // maximum value for red
  362. YellowLimit = 0; // maximum value for yellow
  363. }
  364. /***********************************************************************************************
  365. * TriColorGaugeClass::Set_Red_Limit -- Set the value for the red area of gauge. *
  366. * *
  367. * INPUT: int value. *
  368. * *
  369. * OUTPUT: bool true of false. *
  370. * *
  371. * WARNINGS: none. *
  372. * *
  373. * HISTORY: 01/16/1995 MML : Created. *
  374. *=============================================================================================*/
  375. int TriColorGaugeClass::Set_Red_Limit(int value)
  376. {
  377. if (value >= 0 && value < MaxValue) {
  378. // if (value > YellowLimit) {
  379. // RedLimit = YellowLimit;
  380. // YellowLimit = value;
  381. // } else {
  382. RedLimit = value;
  383. // }
  384. Flag_To_Redraw();
  385. return(true);
  386. }
  387. return(false);
  388. }
  389. /***********************************************************************************************
  390. * TriColorGaugeClass::Set_Yellow_Limit -- Set the value for the yellow area of gauge. *
  391. * *
  392. * INPUT: int value. *
  393. * *
  394. * OUTPUT: bool true of false. *
  395. * *
  396. * WARNINGS: none. *
  397. * *
  398. * HISTORY: 01/16/1995 MML : Created. *
  399. *=============================================================================================*/
  400. int TriColorGaugeClass::Set_Yellow_Limit(int value)
  401. {
  402. if (value >= 0 && value < MaxValue) {
  403. // if (value < RedLimit) {
  404. // YellowLimit = RedLimit;
  405. // RedLimit = value;
  406. // } else {
  407. YellowLimit = value;
  408. // }
  409. Flag_To_Redraw();
  410. return(true);
  411. }
  412. return(false);
  413. }
  414. /***********************************************************************************************
  415. * TriColorGaugeClass::Draw_Me -- Draw the tri color gauge. *
  416. * *
  417. * INPUT: int forced -- draw or not? *
  418. * *
  419. * OUTPUT: bool true of false. *
  420. * *
  421. * WARNINGS: none. *
  422. * *
  423. * HISTORY: 01/16/1995 MML : Created. *
  424. *=============================================================================================*/
  425. int TriColorGaugeClass::Draw_Me(int forced)
  426. {
  427. if (ControlClass::Draw_Me(forced)) {
  428. /*
  429. ===================== Hide the mouse =====================
  430. */
  431. if (LogicPage == &SeenBuff) {
  432. Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
  433. }
  434. /*
  435. =========== Draw the body & set text color ===============
  436. */
  437. Draw_Box (X, Y, Width, Height, (IsDisabled ? BOXSTYLE_GREEN_RAISED : BOXSTYLE_GREEN_DOWN), true);
  438. /*
  439. ** Colorize the inside of the gauge if indicated.
  440. */
  441. int red = Value_To_Pixel(RedLimit);
  442. int yellow = Value_To_Pixel(YellowLimit);
  443. int middle = Value_To_Pixel(CurValue);
  444. if (CurValue <= RedLimit) {
  445. if (IsHorizontal) {
  446. LogicPage->Fill_Rect(X+1, Y+1, middle, Y+Height-2, PINK);
  447. } else {
  448. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, middle, PINK);
  449. }
  450. } else if (CurValue > RedLimit && CurValue <= YellowLimit) {
  451. if (IsHorizontal) {
  452. LogicPage->Fill_Rect(X+1, Y+1, red, Y+Height-2, PINK);
  453. LogicPage->Fill_Rect(red, Y+1, middle, Y+Height-2, YELLOW);
  454. } else {
  455. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red, PINK);
  456. LogicPage->Fill_Rect(X+1, red, X+Width-2, middle, YELLOW);
  457. }
  458. } else if (CurValue > YellowLimit && CurValue <= MaxValue) {
  459. if (IsHorizontal) {
  460. LogicPage->Fill_Rect(X+1, Y+1, red, Y+Height-2, PINK);
  461. LogicPage->Fill_Rect(red, Y+1, yellow, Y+Height-2, YELLOW);
  462. LogicPage->Fill_Rect(yellow, Y+1, middle, Y+Height-2, GREEN);
  463. } else {
  464. LogicPage->Fill_Rect(X+1, Y+1, X+Width-2, red, PINK);
  465. LogicPage->Fill_Rect(X+1, red, X+Width-2, yellow, YELLOW);
  466. LogicPage->Fill_Rect(X+1, yellow, X+Width-2, middle, GREEN);
  467. }
  468. }
  469. if (HasThumb)
  470. Draw_Thumb();
  471. /*
  472. =================== Display the mouse ===================
  473. */
  474. if (LogicPage == &SeenBuff) {
  475. Conditional_Show_Mouse();
  476. }
  477. return(true);
  478. }
  479. return(false);
  480. }