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