GSCREEN.CPP 28 KB

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