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