GSCREEN.CPP (28580B)
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/GSCREEN.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 : GSCREEN.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 12/15/94 * 28 * * 29 * Last Update : January 19, 1995 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * GScreenClass::Add_A_Button -- Add a gadget to the game input system. * 34 * GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage. * 35 * GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn. * 36 * GScreenClass::GScreenClass -- Default constructor for GScreenClass. * 37 * GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines. * 38 * GScreenClass::Init_Clear -- Sets the map to a known state. * 39 * GScreenClass::Init_IO -- Initializes the Button list ('Buttons'). * 40 * GScreenClass::Init_Theater -- Performs theater-specific initializations. * 41 * GScreenClass::Input -- Fetches input and processes gadgets. * 42 * GScreenClass::One_Time -- Handles one time class setups. * 43 * GScreenClass::Remove_A_Button -- Removes a gadget from the game input system. * 44 * GScreenClass::Render -- General drawing dispatcher an display update function. * 45 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 46 47 #include "function.h" 48 49 50 GadgetClass * GScreenClass::Buttons = 0; 51 52 GraphicBufferClass * GScreenClass::ShadowPage = 0; 53 54 55 /*********************************************************************************************** 56 * GScreenClass::GScreenClass -- Default constructor for GScreenClass. * 57 * * 58 * This constructor merely sets the display system, so that it will redraw the first time * 59 * the render function is called. * 60 * * 61 * INPUT: none * 62 * * 63 * OUTPUT: none * 64 * * 65 * WARNINGS: none * 66 * * 67 * HISTORY: * 68 * 12/15/1994 JLB : Created. * 69 *=============================================================================================*/ 70 GScreenClass::GScreenClass(void) 71 { 72 IsToUpdate = true; 73 IsToRedraw = true; 74 } 75 76 77 /*********************************************************************************************** 78 * GScreenClass::One_Time -- Handles one time class setups. * 79 * * 80 * This routine (and all those that overload it) must perform truly one-time initialization. * 81 * Such init's would normally be done in the constructor, but other aspects of the game may * 82 * not have been initialized at the time the constructors are called (such as the file system, * 83 * the display, or other WWLIB subsystems), so many initializations should be deferred to the * 84 * One_Time init's. * 85 * * 86 * Any variables set in this routine should be declared as static, so they won't be modified * 87 * by the load/save process. Non-static variables will be over-written by a loaded game. * 88 * * 89 * This function allocates the shadow buffer that is used for quick screen updates. If * 90 * there were any data files to load, they would be loaded at this time as well. * 91 * * 92 * INPUT: none * 93 * * 94 * OUTPUT: none * 95 * * 96 * WARNINGS: Call this routine only ONCE at the beginning of the game. * 97 * * 98 * HISTORY: * 99 * 12/15/1994 JLB : Created. * 100 *=============================================================================================*/ 101 void GScreenClass::One_Time(void) 102 { 103 /* 104 ** Allocate the screen shadow page. This page is used to reduce access to the 105 ** actual screen memory. It contains a duplicate of what the SEENPAGE is. 106 */ 107 Buttons = 0; 108 ShadowPage = new GraphicBufferClass(320, 200); 109 if (ShadowPage) { 110 ShadowPage->Clear(); 111 HidPage.Clear(); 112 } 113 } 114 115 116 /*********************************************************************************************** 117 * GScreenClass::Init -- Init's the entire display hierarchy by calling all Init routines. * 118 * * 119 * This routine shouldn't be overloaded. It's the main map initialization routine, and will * 120 * perform a complete map initialization, from mixfiles to clearing the buffers. Calling this * 121 * routine results in calling every initialization routine in the entire map hierarchy. * 122 * * 123 * INPUT: * 124 * theater theater to initialize to * 125 * * 126 * OUTPUT: * 127 * none. * 128 * * 129 * WARNINGS: * 130 * none. * 131 * * 132 * HISTORY: * 133 * 12/28/1994 BR : Created. * 134 *=============================================================================================*/ 135 void GScreenClass::Init(TheaterType theater) 136 { 137 Init_Clear(); 138 Init_IO(); 139 Init_Theater(theater); 140 } 141 142 143 /*********************************************************************************************** 144 * GScreenClass::Init_Clear -- Sets the map to a known state. * 145 * * 146 * This routine (and those that overload it) clears any buffers and variables to a known * 147 * state. It assumes that all buffers are allocated & valid. The map should be displayable * 148 * after calling this function, and should draw basically an empty display. * 149 * * 150 * INPUT: * 151 * none. * 152 * * 153 * OUTPUT: * 154 * none. * 155 * * 156 * WARNINGS: * 157 * none. * 158 * * 159 * HISTORY: * 160 * 12/28/1994 BR : Created. * 161 *=============================================================================================*/ 162 void GScreenClass::Init_Clear(void) 163 { 164 /* 165 ** Clear the ShadowPage & HidPage to force a complete shadow blit. 166 */ 167 if (ShadowPage) { 168 ShadowPage->Clear(); 169 HidPage.Clear(); 170 } 171 172 IsToRedraw = true; 173 } 174 175 176 /*********************************************************************************************** 177 * GScreenClass::Init_Theater -- Performs theater-specific initializations. * 178 * * 179 * This routine (and those that overload it) performs any theater-specific initializations * 180 * needed. This will include setting the palette, setting up remap tables, etc. This routine * 181 * only needs to be called when the theater has changed. * 182 * * 183 * INPUT: * 184 * none. * 185 * * 186 * OUTPUT: * 187 * none. * 188 * * 189 * WARNINGS: * 190 * none. * 191 * * 192 * HISTORY: * 193 * 12/28/1994 BR : Created. * 194 *=============================================================================================*/ 195 void GScreenClass::Init_Theater(TheaterType ) 196 { 197 } 198 199 200 /*********************************************************************************************** 201 * GScreenClass::Init_IO -- Initializes the Button list ('Buttons'). * 202 * * 203 * INPUT: * 204 * none. * 205 * * 206 * OUTPUT: * 207 * none. * 208 * * 209 * WARNINGS: * 210 * none. * 211 * * 212 * HISTORY: * 213 * 12/28/1994 BR : Created. * 214 *=============================================================================================*/ 215 void GScreenClass::Init_IO(void) 216 { 217 /* 218 ** Reset the button list. This means that any other elements of the map that need 219 ** buttons must attach them after this routine is called! 220 */ 221 Buttons = 0; 222 } 223 224 225 /*********************************************************************************************** 226 * GScreenClass::Flag_To_Redraw -- Flags the display to be redrawn. * 227 * * 228 * This function is used to flag the display system whether any rendering is needed. The * 229 * parameter tells the system either to redraw EVERYTHING, or just that something somewhere * 230 * has changed and the individual Draw_It functions must be called. When a sub system * 231 * determines that it needs to render something local to itself, it would call this routine * 232 * with a false parameter. If the entire screen gets trashed or needs to be rebuilt, then * 233 * this routine will be called with a true parameter. * 234 * * 235 * INPUT: complete -- bool; Should the ENTIRE screen be redrawn? * 236 * * 237 * OUTPUT: none * 238 * * 239 * WARNINGS: This doesn't actually draw the screen, it merely sets flags so that when the * 240 * Render() function is called, the appropriate drawing steps will be performed. * 241 * * 242 * HISTORY: * 243 * 12/15/1994 JLB : Created. * 244 *=============================================================================================*/ 245 void GScreenClass::Flag_To_Redraw(bool complete) 246 { 247 IsToUpdate = true; 248 if (complete) { 249 IsToRedraw = true; 250 } 251 } 252 253 254 /*********************************************************************************************** 255 * GScreenClass::Input -- Fetches input and processes gadgets. * 256 * * 257 * This routine will fetch the keyboard/mouse input and dispatch this through the gadget * 258 * system. * 259 * * 260 * INPUT: key -- Reference to the key code (for future examination). * 261 * * 262 * x,y -- Reference to mouse coordinates (for future examination). * 263 * * 264 * OUTPUT: none * 265 * * 266 * WARNINGS: none * 267 * * 268 * HISTORY: * 269 * 01/19/1995 JLB : Created. * 270 *=============================================================================================*/ 271 void GScreenClass::Input(KeyNumType & key, int & x, int & y) 272 { 273 key = Keyboard->Check(); 274 275 x = Keyboard->Mouse_X(); 276 y = Keyboard->Mouse_Y(); 277 278 if (Buttons != NULL) { 279 280 /* 281 ** If any buttons need redrawing, they will do so in the Input routine, and 282 ** they should draw themselves to the HidPage. So, flag ourselves for a Blit 283 ** to show the newly drawn buttons. 284 */ 285 if (Buttons->Is_List_To_Redraw()) { 286 Flag_To_Redraw(false); 287 } 288 289 #ifdef WIN32 290 GraphicViewPortClass * oldpage= Set_Logic_Page(HidPage); 291 #else 292 GraphicBufferClass * oldpage= Set_Logic_Page(HidPage); 293 #endif 294 295 key = Buttons->Input(); 296 297 Set_Logic_Page(oldpage); 298 299 } else { 300 301 if (key != 0) { 302 key = Keyboard->Get(); 303 } 304 } 305 306 AI(key, x, y); 307 } 308 309 310 /*********************************************************************************************** 311 * GScreenClass::Add_A_Button -- Add a gadget to the game input system. * 312 * * 313 * This will add a gadget to the game input system. The gadget will be processed in * 314 * subsequent calls to the GScreenClass::Input() function. * 315 * * 316 * INPUT: gadget -- Reference to the gadget that will be added to the input system. * 317 * * 318 * OUTPUT: none * 319 * * 320 * WARNINGS: none * 321 * * 322 * HISTORY: * 323 * 01/19/1995 JLB : Created. * 324 *=============================================================================================*/ 325 void GScreenClass::Add_A_Button(GadgetClass & gadget) 326 { 327 /* 328 ** If this gadget is already in the list, remove it before adding it in: 329 ** - If 1st gadget in list, use Remove_A_Button to remove it, to reset the 330 ** value of 'Buttons' appropriately 331 ** - Otherwise, just call the Remove function for that gadget to remove it 332 ** from any list it may be in 333 */ 334 if (Buttons == &gadget) { 335 Remove_A_Button(gadget); 336 } else { 337 gadget.Remove(); 338 } 339 340 /* 341 ** Now add the gadget to our list: 342 ** - If there are not buttons, start the list with this one 343 ** - Otherwise, add it to the tail of the existing list 344 */ 345 if (Buttons) { 346 gadget.Add_Tail(*Buttons); 347 } else { 348 Buttons = &gadget; 349 } 350 } 351 352 353 /*********************************************************************************************** 354 * GScreenClass::Remove_A_Button -- Removes a gadget from the game input system. * 355 * * 356 * INPUT: gadget -- Reference to the gadget that will be removed from the input system. * 357 * * 358 * OUTPUT: none * 359 * * 360 * WARNINGS: 'gadget' MUST be already a part of 'Buttons', or the new value of 'Buttons' * 361 * will be invalid! * 362 * * 363 * HISTORY: * 364 * 01/19/1995 JLB : Created. * 365 *=============================================================================================*/ 366 void GScreenClass::Remove_A_Button(GadgetClass & gadget) 367 { 368 Buttons = gadget.Remove(); 369 } 370 371 372 /*********************************************************************************************** 373 * GScreenClass::Render -- General drawing dispatcher an display update function. * 374 * * 375 * This routine should be called in the main game loop (once every game frame). It will * 376 * call the Draw_It() function if necessary. All rendering is performed to the LogicPage * 377 * which is set to the HIDPAGE. After rendering has been performed, the HIDPAGE is * 378 * copied to the visible page. * 379 * * 380 * INPUT: none * 381 * * 382 * OUTPUT: none * 383 * * 384 * WARNINGS: This actually updates the graphic display. As a result it can take quite a * 385 * while to perform. * 386 * * 387 * HISTORY: * 388 * 12/15/1994 JLB : Created. * 389 *=============================================================================================*/ 390 void GScreenClass::Render(void) 391 { 392 //This is unnessasary surely? ST - 10/16/96 2:30PM 393 //if (Buttons && Buttons->Is_List_To_Redraw()) { 394 // IsToRedraw = true; 395 //} 396 397 398 if (IsToUpdate || IsToRedraw) { 399 BStart(BENCH_GSCREEN_RENDER); 400 401 #ifdef WIN32 402 GraphicViewPortClass * oldpage= Set_Logic_Page(HidPage); 403 #else 404 GraphicBufferClass * oldpage= Set_Logic_Page(HidPage); 405 406 if (IsToRedraw) { 407 Hide_Mouse(); 408 SeenPage.To_Buffer(0, 0, 320, 200, ShadowPage); 409 Show_Mouse(); 410 } 411 #endif 412 413 Draw_It(IsToRedraw); 414 415 if (Buttons) Buttons->Draw_All(false); 416 417 #ifdef SCENARIO_EDITOR 418 /* 419 ** Draw the Editor's buttons 420 */ 421 if (Debug_Map) { 422 if (Buttons) { 423 Buttons->Draw_All(); 424 } 425 } 426 #endif 427 /* 428 ** Draw the multiplayer message system to the Hidpage at this point. 429 ** This way, they'll Blit along with the rest of the map. 430 */ 431 if (Session.Messages.Num_Messages() > 0) { 432 Session.Messages.Set_Width( 433 Lepton_To_Cell(Map.TacLeptonWidth) * ICON_PIXEL_W); 434 } 435 Session.Messages.Draw(); 436 437 //Blit_Display(); // 5/19/20 SKY - Skip copying to scene page, we can get the data directly from hidden page 438 IsToUpdate = false; 439 IsToRedraw = false; 440 441 BEnd(BENCH_GSCREEN_RENDER); 442 Set_Logic_Page(oldpage); 443 } 444 } 445 446 447 /*********************************************************************************************** 448 * GScreenClass::Blit_Display -- Redraw the display from the hidpage to the seenpage. * 449 * * 450 * This routine is used to copy the correct display from the HIDPAGE * 451 * to the SEENPAGE. * 452 * * 453 * INPUT: none * 454 * * 455 * OUTPUT: none * 456 * * 457 * WARNINGS: none * 458 * * 459 * HISTORY: * 460 * 02/14/1994 JLB : Created. * 461 * 05/01/1994 JLB : Converted to member function. * 462 *=============================================================================================*/ 463 extern "C" { 464 void ModeX_Blit (GraphicBufferClass * source); 465 } 466 467 void GScreenClass::Blit_Display(void) 468 { 469 BStart(BENCH_BLIT_DISPLAY); 470 #ifdef WIN32 471 if (SeenBuff.Get_Width()!=320) { 472 WWMouse->Draw_Mouse(&HidPage); 473 HidPage.Blit(SeenBuff , 0 , 0 , 0 , 0 , HidPage.Get_Width() , HidPage.Get_Height() , (BOOL) FALSE ); 474 WWMouse->Erase_Mouse(&HidPage, FALSE); 475 } else { 476 //PG ModeX_Blit(&HiddenPage); 477 } 478 #else 479 Shadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ShadowPage->Get_Buffer()); 480 #endif 481 BEnd(BENCH_BLIT_DISPLAY); 482 } 483 484