Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | Copyright (C) 1996-1997 Id Software, Inc. |
||
3 | |||
4 | This program is free software; you can redistribute it and/or |
||
5 | modify it under the terms of the GNU General Public License |
||
6 | as published by the Free Software Foundation; either version 2 |
||
7 | of the License, or (at your option) any later version. |
||
8 | |||
9 | This program is distributed in the hope that it will be useful, |
||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | |||
13 | See the 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, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
18 | |||
19 | */ |
||
20 | |||
21 | // screen.c -- master for refresh, status bar, console, chat, notify, etc |
||
22 | |||
23 | #include "quakedef.h" |
||
24 | |||
25 | /* |
||
26 | |||
27 | background clear |
||
28 | rendering |
||
29 | turtle/net/ram icons |
||
30 | sbar |
||
31 | centerprint / slow centerprint |
||
32 | notify lines |
||
33 | intermission / finale overlay |
||
34 | loading plaque |
||
35 | console |
||
36 | menu |
||
37 | |||
38 | required background clears |
||
39 | required update regions |
||
40 | |||
41 | |||
42 | syncronous draw mode or async |
||
43 | One off screen buffer, with updates either copied or xblited |
||
44 | Need to double buffer? |
||
45 | |||
46 | |||
47 | async draw will require the refresh area to be cleared, because it will be |
||
48 | xblited, but sync draw can just ignore it. |
||
49 | |||
50 | sync |
||
51 | draw |
||
52 | |||
53 | CenterPrint () |
||
54 | SlowPrint () |
||
55 | Screen_Update (); |
||
56 | Con_Printf (); |
||
57 | |||
58 | net |
||
59 | turn off messages option |
||
60 | |||
61 | the refresh is allways rendered, unless the console is full screen |
||
62 | |||
63 | |||
64 | console is: |
||
65 | notify lines |
||
66 | half |
||
67 | full |
||
68 | |||
69 | |||
70 | */ |
||
71 | |||
72 | |||
73 | int glx, gly, glwidth, glheight; |
||
74 | |||
75 | // only the refresh window will be updated unless these variables are flagged |
||
76 | int scr_copytop; |
||
77 | int scr_copyeverything; |
||
78 | |||
79 | float scr_con_current; |
||
80 | float scr_conlines; // lines of console to display |
||
81 | |||
82 | float oldscreensize, oldfov; |
||
83 | cvar_t scr_viewsize = {"viewsize","100", true}; |
||
84 | cvar_t scr_fov = {"fov","90"}; // 10 - 170 |
||
85 | cvar_t scr_conspeed = {"scr_conspeed","300"}; |
||
86 | cvar_t scr_centertime = {"scr_centertime","2"}; |
||
87 | cvar_t scr_showram = {"showram","1"}; |
||
88 | cvar_t scr_showturtle = {"showturtle","0"}; |
||
89 | cvar_t scr_showpause = {"showpause","1"}; |
||
90 | cvar_t scr_printspeed = {"scr_printspeed","8"}; |
||
91 | cvar_t gl_triplebuffer = {"gl_triplebuffer", "1", true }; |
||
92 | |||
93 | extern cvar_t crosshair; |
||
94 | |||
95 | qboolean scr_initialized; // ready to draw |
||
96 | |||
97 | qpic_t *scr_ram; |
||
98 | qpic_t *scr_net; |
||
99 | qpic_t *scr_turtle; |
||
100 | |||
101 | int scr_fullupdate; |
||
102 | |||
103 | int clearconsole; |
||
104 | int clearnotify; |
||
105 | |||
106 | int sb_lines; |
||
107 | |||
108 | viddef_t vid; // global video state |
||
109 | |||
110 | vrect_t scr_vrect; |
||
111 | |||
112 | qboolean scr_disabled_for_loading; |
||
113 | qboolean scr_drawloading; |
||
114 | float scr_disabled_time; |
||
115 | |||
116 | qboolean block_drawing; |
||
117 | |||
118 | void SCR_ScreenShot_f (void); |
||
119 | |||
120 | /* |
||
121 | =============================================================================== |
||
122 | |||
123 | CENTER PRINTING |
||
124 | |||
125 | =============================================================================== |
||
126 | */ |
||
127 | |||
128 | char scr_centerstring[1024]; |
||
129 | float scr_centertime_start; // for slow victory printing |
||
130 | float scr_centertime_off; |
||
131 | int scr_center_lines; |
||
132 | int scr_erase_lines; |
||
133 | int scr_erase_center; |
||
134 | |||
135 | /* |
||
136 | ============== |
||
137 | SCR_CenterPrint |
||
138 | |||
139 | Called for important messages that should stay in the center of the screen |
||
140 | for a few moments |
||
141 | ============== |
||
142 | */ |
||
143 | void SCR_CenterPrint (char *str) |
||
144 | { |
||
145 | strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); |
||
146 | scr_centertime_off = scr_centertime.value; |
||
147 | scr_centertime_start = cl.time; |
||
148 | |||
149 | // count the number of lines for centering |
||
150 | scr_center_lines = 1; |
||
151 | while (*str) |
||
152 | { |
||
153 | if (*str == '\n') |
||
154 | scr_center_lines++; |
||
155 | str++; |
||
156 | } |
||
157 | } |
||
158 | |||
159 | |||
160 | void SCR_DrawCenterString (void) |
||
161 | { |
||
162 | char *start; |
||
163 | int l; |
||
164 | int j; |
||
165 | int x, y; |
||
166 | int remaining; |
||
167 | |||
168 | // the finale prints the characters one at a time |
||
169 | if (cl.intermission) |
||
170 | remaining = scr_printspeed.value * (cl.time - scr_centertime_start); |
||
171 | else |
||
172 | remaining = 9999; |
||
173 | |||
174 | scr_erase_center = 0; |
||
175 | start = scr_centerstring; |
||
176 | |||
177 | if (scr_center_lines <= 4) |
||
178 | y = vid.height*0.35; |
||
179 | else |
||
180 | y = 48; |
||
181 | |||
182 | do |
||
183 | { |
||
184 | // scan the width of the line |
||
185 | for (l=0 ; l<40 ; l++) |
||
186 | if (start[l] == '\n' || !start[l]) |
||
187 | break; |
||
188 | x = (vid.width - l*8)/2; |
||
189 | for (j=0 ; j |
||
190 | { |
||
191 | Draw_Character (x, y, start[j]); |
||
192 | if (!remaining--) |
||
193 | return; |
||
194 | } |
||
195 | |||
196 | y += 8; |
||
197 | |||
198 | while (*start && *start != '\n') |
||
199 | start++; |
||
200 | |||
201 | if (!*start) |
||
202 | break; |
||
203 | start++; // skip the \n |
||
204 | } while (1); |
||
205 | } |
||
206 | |||
207 | void SCR_CheckDrawCenterString (void) |
||
208 | { |
||
209 | scr_copytop = 1; |
||
210 | if (scr_center_lines > scr_erase_lines) |
||
211 | scr_erase_lines = scr_center_lines; |
||
212 | |||
213 | scr_centertime_off -= host_frametime; |
||
214 | |||
215 | if (scr_centertime_off <= 0 && !cl.intermission) |
||
216 | return; |
||
217 | if (key_dest != key_game) |
||
218 | return; |
||
219 | |||
220 | SCR_DrawCenterString (); |
||
221 | } |
||
222 | |||
223 | //============================================================================= |
||
224 | |||
225 | /* |
||
226 | ==================== |
||
227 | CalcFov |
||
228 | ==================== |
||
229 | */ |
||
230 | float CalcFov (float fov_x, float width, float height) |
||
231 | { |
||
232 | float a; |
||
233 | float x; |
||
234 | |||
235 | if (fov_x < 1 || fov_x > 179) |
||
236 | Sys_Error ("Bad fov: %f", fov_x); |
||
237 | |||
238 | x = width/tan(fov_x/360*M_PI); |
||
239 | |||
240 | a = atan (height/x); |
||
241 | |||
242 | a = a*360/M_PI; |
||
243 | |||
244 | return a; |
||
245 | } |
||
246 | |||
247 | /* |
||
248 | ================= |
||
249 | SCR_CalcRefdef |
||
250 | |||
251 | Must be called whenever vid changes |
||
252 | Internal use only |
||
253 | ================= |
||
254 | */ |
||
255 | static void SCR_CalcRefdef (void) |
||
256 | { |
||
257 | vrect_t vrect; |
||
258 | float size; |
||
259 | int h; |
||
260 | qboolean full = false; |
||
261 | |||
262 | |||
263 | scr_fullupdate = 0; // force a background redraw |
||
264 | vid.recalc_refdef = 0; |
||
265 | |||
266 | // force the status bar to redraw |
||
267 | Sbar_Changed (); |
||
268 | |||
269 | //======================================== |
||
270 | |||
271 | // bound viewsize |
||
272 | if (scr_viewsize.value < 30) |
||
273 | Cvar_Set ("viewsize","30"); |
||
274 | if (scr_viewsize.value > 120) |
||
275 | Cvar_Set ("viewsize","120"); |
||
276 | |||
277 | // bound field of view |
||
278 | if (scr_fov.value < 10) |
||
279 | Cvar_Set ("fov","10"); |
||
280 | if (scr_fov.value > 170) |
||
281 | Cvar_Set ("fov","170"); |
||
282 | |||
283 | // intermission is always full screen |
||
284 | if (cl.intermission) |
||
285 | size = 120; |
||
286 | else |
||
287 | size = scr_viewsize.value; |
||
288 | |||
289 | if (size >= 120) |
||
290 | sb_lines = 0; // no status bar at all |
||
291 | else if (size >= 110) |
||
292 | sb_lines = 24; // no inventory |
||
293 | else |
||
294 | sb_lines = 24+16+8; |
||
295 | |||
296 | if (scr_viewsize.value >= 100.0) { |
||
297 | full = true; |
||
298 | size = 100.0; |
||
299 | } else |
||
300 | size = scr_viewsize.value; |
||
301 | if (cl.intermission) |
||
302 | { |
||
303 | full = true; |
||
304 | size = 100; |
||
305 | sb_lines = 0; |
||
306 | } |
||
307 | size /= 100.0; |
||
308 | |||
309 | h = vid.height - sb_lines; |
||
310 | |||
311 | r_refdef.vrect.width = vid.width * size; |
||
312 | if (r_refdef.vrect.width < 96) |
||
313 | { |
||
314 | size = 96.0 / r_refdef.vrect.width; |
||
315 | r_refdef.vrect.width = 96; // min for icons |
||
316 | } |
||
317 | |||
318 | r_refdef.vrect.height = vid.height * size; |
||
319 | if (r_refdef.vrect.height > vid.height - sb_lines) |
||
320 | r_refdef.vrect.height = vid.height - sb_lines; |
||
321 | if (r_refdef.vrect.height > vid.height) |
||
322 | r_refdef.vrect.height = vid.height; |
||
323 | r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; |
||
324 | if (full) |
||
325 | r_refdef.vrect.y = 0; |
||
326 | else |
||
327 | r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; |
||
328 | |||
329 | r_refdef.fov_x = scr_fov.value; |
||
330 | r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); |
||
331 | |||
332 | scr_vrect = r_refdef.vrect; |
||
333 | } |
||
334 | |||
335 | |||
336 | /* |
||
337 | ================= |
||
338 | SCR_SizeUp_f |
||
339 | |||
340 | Keybinding command |
||
341 | ================= |
||
342 | */ |
||
343 | void SCR_SizeUp_f (void) |
||
344 | { |
||
345 | Cvar_SetValue ("viewsize",scr_viewsize.value+10); |
||
346 | vid.recalc_refdef = 1; |
||
347 | } |
||
348 | |||
349 | |||
350 | /* |
||
351 | ================= |
||
352 | SCR_SizeDown_f |
||
353 | |||
354 | Keybinding command |
||
355 | ================= |
||
356 | */ |
||
357 | void SCR_SizeDown_f (void) |
||
358 | { |
||
359 | Cvar_SetValue ("viewsize",scr_viewsize.value-10); |
||
360 | vid.recalc_refdef = 1; |
||
361 | } |
||
362 | |||
363 | //============================================================================ |
||
364 | |||
365 | /* |
||
366 | ================== |
||
367 | SCR_Init |
||
368 | ================== |
||
369 | */ |
||
370 | void SCR_Init (void) |
||
371 | { |
||
372 | |||
373 | Cvar_RegisterVariable (&scr_fov); |
||
374 | Cvar_RegisterVariable (&scr_viewsize); |
||
375 | Cvar_RegisterVariable (&scr_conspeed); |
||
376 | Cvar_RegisterVariable (&scr_showram); |
||
377 | Cvar_RegisterVariable (&scr_showturtle); |
||
378 | Cvar_RegisterVariable (&scr_showpause); |
||
379 | Cvar_RegisterVariable (&scr_centertime); |
||
380 | Cvar_RegisterVariable (&scr_printspeed); |
||
381 | Cvar_RegisterVariable (&gl_triplebuffer); |
||
382 | |||
383 | // |
||
384 | // register our commands |
||
385 | // |
||
386 | Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); |
||
387 | Cmd_AddCommand ("sizeup",SCR_SizeUp_f); |
||
388 | Cmd_AddCommand ("sizedown",SCR_SizeDown_f); |
||
389 | |||
390 | scr_ram = Draw_PicFromWad ("ram"); |
||
391 | scr_net = Draw_PicFromWad ("net"); |
||
392 | scr_turtle = Draw_PicFromWad ("turtle"); |
||
393 | |||
394 | scr_initialized = true; |
||
395 | } |
||
396 | |||
397 | |||
398 | |||
399 | /* |
||
400 | ============== |
||
401 | SCR_DrawRam |
||
402 | ============== |
||
403 | */ |
||
404 | void SCR_DrawRam (void) |
||
405 | { |
||
406 | if (!scr_showram.value) |
||
407 | return; |
||
408 | |||
409 | if (!r_cache_thrash) |
||
410 | return; |
||
411 | |||
412 | Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram); |
||
413 | } |
||
414 | |||
415 | /* |
||
416 | ============== |
||
417 | SCR_DrawTurtle |
||
418 | ============== |
||
419 | */ |
||
420 | void SCR_DrawTurtle (void) |
||
421 | { |
||
422 | static int count; |
||
423 | |||
424 | if (!scr_showturtle.value) |
||
425 | return; |
||
426 | |||
427 | if (host_frametime < 0.1) |
||
428 | { |
||
429 | count = 0; |
||
430 | return; |
||
431 | } |
||
432 | |||
433 | count++; |
||
434 | if (count < 3) |
||
435 | return; |
||
436 | |||
437 | Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); |
||
438 | } |
||
439 | |||
440 | /* |
||
441 | ============== |
||
442 | SCR_DrawNet |
||
443 | ============== |
||
444 | */ |
||
445 | void SCR_DrawNet (void) |
||
446 | { |
||
447 | if (realtime - cl.last_received_message < 0.3) |
||
448 | return; |
||
449 | if (cls.demoplayback) |
||
450 | return; |
||
451 | |||
452 | Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net); |
||
453 | } |
||
454 | |||
455 | /* |
||
456 | ============== |
||
457 | DrawPause |
||
458 | ============== |
||
459 | */ |
||
460 | void SCR_DrawPause (void) |
||
461 | { |
||
462 | qpic_t *pic; |
||
463 | |||
464 | if (!scr_showpause.value) // turn off for screenshots |
||
465 | return; |
||
466 | |||
467 | if (!cl.paused) |
||
468 | return; |
||
469 | |||
470 | pic = Draw_CachePic ("gfx/pause.lmp"); |
||
471 | Draw_Pic ( (vid.width - pic->width)/2, |
||
472 | (vid.height - 48 - pic->height)/2, pic); |
||
473 | } |
||
474 | |||
475 | |||
476 | |||
477 | /* |
||
478 | ============== |
||
479 | SCR_DrawLoading |
||
480 | ============== |
||
481 | */ |
||
482 | void SCR_DrawLoading (void) |
||
483 | { |
||
484 | qpic_t *pic; |
||
485 | |||
486 | if (!scr_drawloading) |
||
487 | return; |
||
488 | |||
489 | pic = Draw_CachePic ("gfx/loading.lmp"); |
||
490 | Draw_Pic ( (vid.width - pic->width)/2, |
||
491 | (vid.height - 48 - pic->height)/2, pic); |
||
492 | } |
||
493 | |||
494 | |||
495 | |||
496 | //============================================================================= |
||
497 | |||
498 | |||
499 | /* |
||
500 | ================== |
||
501 | SCR_SetUpToDrawConsole |
||
502 | ================== |
||
503 | */ |
||
504 | void SCR_SetUpToDrawConsole (void) |
||
505 | { |
||
506 | Con_CheckResize (); |
||
507 | |||
508 | if (scr_drawloading) |
||
509 | return; // never a console with loading plaque |
||
510 | |||
511 | // decide on the height of the console |
||
512 | con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; |
||
513 | |||
514 | if (con_forcedup) |
||
515 | { |
||
516 | scr_conlines = vid.height; // full screen |
||
517 | scr_con_current = scr_conlines; |
||
518 | } |
||
519 | else if (key_dest == key_console) |
||
520 | scr_conlines = vid.height/2; // half screen |
||
521 | else |
||
522 | scr_conlines = 0; // none visible |
||
523 | |||
524 | if (scr_conlines < scr_con_current) |
||
525 | { |
||
526 | scr_con_current -= scr_conspeed.value*host_frametime; |
||
527 | if (scr_conlines > scr_con_current) |
||
528 | scr_con_current = scr_conlines; |
||
529 | |||
530 | } |
||
531 | else if (scr_conlines > scr_con_current) |
||
532 | { |
||
533 | scr_con_current += scr_conspeed.value*host_frametime; |
||
534 | if (scr_conlines < scr_con_current) |
||
535 | scr_con_current = scr_conlines; |
||
536 | } |
||
537 | |||
538 | if (clearconsole++ < vid.numpages) |
||
539 | { |
||
540 | Sbar_Changed (); |
||
541 | } |
||
542 | else if (clearnotify++ < vid.numpages) |
||
543 | { |
||
544 | } |
||
545 | else |
||
546 | con_notifylines = 0; |
||
547 | } |
||
548 | |||
549 | /* |
||
550 | ================== |
||
551 | SCR_DrawConsole |
||
552 | ================== |
||
553 | */ |
||
554 | void SCR_DrawConsole (void) |
||
555 | { |
||
556 | if (scr_con_current) |
||
557 | { |
||
558 | scr_copyeverything = 1; |
||
559 | Con_DrawConsole (scr_con_current, true); |
||
560 | clearconsole = 0; |
||
561 | } |
||
562 | else |
||
563 | { |
||
564 | if (key_dest == key_game || key_dest == key_message) |
||
565 | Con_DrawNotify (); // only draw notify in game |
||
566 | } |
||
567 | } |
||
568 | |||
569 | |||
570 | /* |
||
571 | ============================================================================== |
||
572 | |||
573 | SCREEN SHOTS |
||
574 | |||
575 | ============================================================================== |
||
576 | */ |
||
577 | |||
578 | typedef struct _TargaHeader { |
||
579 | unsigned char id_length, colormap_type, image_type; |
||
580 | unsigned short colormap_index, colormap_length; |
||
581 | unsigned char colormap_size; |
||
582 | unsigned short x_origin, y_origin, width, height; |
||
583 | unsigned char pixel_size, attributes; |
||
584 | } TargaHeader; |
||
585 | |||
586 | |||
587 | /* |
||
588 | ================== |
||
589 | SCR_ScreenShot_f |
||
590 | ================== |
||
591 | */ |
||
592 | void SCR_ScreenShot_f (void) |
||
593 | { |
||
594 | byte *buffer; |
||
595 | char pcxname[80]; |
||
596 | char checkname[MAX_OSPATH]; |
||
597 | int i, c, temp; |
||
598 | // |
||
599 | // find a file name to save it to |
||
600 | // |
||
601 | strcpy(pcxname,"quake00.tga"); |
||
602 | |||
603 | for (i=0 ; i<=99 ; i++) |
||
604 | { |
||
605 | pcxname[5] = i/10 + '0'; |
||
606 | pcxname[6] = i%10 + '0'; |
||
607 | sprintf (checkname, "%s/%s", com_gamedir, pcxname); |
||
608 | if (Sys_FileTime(checkname) == -1) |
||
609 | break; // file doesn't exist |
||
610 | } |
||
611 | if (i==100) |
||
612 | { |
||
613 | Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX file\n"); |
||
614 | return; |
||
615 | } |
||
616 | |||
617 | |||
618 | buffer = malloc(glwidth*glheight*3 + 18); |
||
619 | memset (buffer, 0, 18); |
||
620 | buffer[2] = 2; // uncompressed type |
||
621 | buffer[12] = glwidth&255; |
||
622 | buffer[13] = glwidth>>8; |
||
623 | buffer[14] = glheight&255; |
||
624 | buffer[15] = glheight>>8; |
||
625 | buffer[16] = 24; // pixel size |
||
626 | |||
627 | glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); |
||
628 | |||
629 | // swap rgb to bgr |
||
630 | c = 18+glwidth*glheight*3; |
||
631 | for (i=18 ; i |
||
632 | { |
||
633 | temp = buffer[i]; |
||
634 | buffer[i] = buffer[i+2]; |
||
635 | buffer[i+2] = temp; |
||
636 | } |
||
637 | COM_WriteFile (pcxname, buffer, glwidth*glheight*3 + 18 ); |
||
638 | |||
639 | free (buffer); |
||
640 | Con_Printf ("Wrote %s\n", pcxname); |
||
641 | } |
||
642 | |||
643 | |||
644 | //============================================================================= |
||
645 | |||
646 | |||
647 | /* |
||
648 | =============== |
||
649 | SCR_BeginLoadingPlaque |
||
650 | |||
651 | ================ |
||
652 | */ |
||
653 | void SCR_BeginLoadingPlaque (void) |
||
654 | { |
||
655 | S_StopAllSounds (true); |
||
656 | |||
657 | if (cls.state != ca_connected) |
||
658 | return; |
||
659 | if (cls.signon != SIGNONS) |
||
660 | return; |
||
661 | |||
662 | // redraw with no console and the loading plaque |
||
663 | Con_ClearNotify (); |
||
664 | scr_centertime_off = 0; |
||
665 | scr_con_current = 0; |
||
666 | |||
667 | scr_drawloading = true; |
||
668 | scr_fullupdate = 0; |
||
669 | Sbar_Changed (); |
||
670 | SCR_UpdateScreen (); |
||
671 | scr_drawloading = false; |
||
672 | |||
673 | scr_disabled_for_loading = true; |
||
674 | scr_disabled_time = realtime; |
||
675 | scr_fullupdate = 0; |
||
676 | } |
||
677 | |||
678 | /* |
||
679 | =============== |
||
680 | SCR_EndLoadingPlaque |
||
681 | |||
682 | ================ |
||
683 | */ |
||
684 | void SCR_EndLoadingPlaque (void) |
||
685 | { |
||
686 | scr_disabled_for_loading = false; |
||
687 | scr_fullupdate = 0; |
||
688 | Con_ClearNotify (); |
||
689 | } |
||
690 | |||
691 | //============================================================================= |
||
692 | |||
693 | char *scr_notifystring; |
||
694 | qboolean scr_drawdialog; |
||
695 | |||
696 | void SCR_DrawNotifyString (void) |
||
697 | { |
||
698 | char *start; |
||
699 | int l; |
||
700 | int j; |
||
701 | int x, y; |
||
702 | |||
703 | start = scr_notifystring; |
||
704 | |||
705 | y = vid.height*0.35; |
||
706 | |||
707 | do |
||
708 | { |
||
709 | // scan the width of the line |
||
710 | for (l=0 ; l<40 ; l++) |
||
711 | if (start[l] == '\n' || !start[l]) |
||
712 | break; |
||
713 | x = (vid.width - l*8)/2; |
||
714 | for (j=0 ; j |
||
715 | Draw_Character (x, y, start[j]); |
||
716 | |||
717 | y += 8; |
||
718 | |||
719 | while (*start && *start != '\n') |
||
720 | start++; |
||
721 | |||
722 | if (!*start) |
||
723 | break; |
||
724 | start++; // skip the \n |
||
725 | } while (1); |
||
726 | } |
||
727 | |||
728 | /* |
||
729 | ================== |
||
730 | SCR_ModalMessage |
||
731 | |||
732 | Displays a text string in the center of the screen and waits for a Y or N |
||
733 | keypress. |
||
734 | ================== |
||
735 | */ |
||
736 | int SCR_ModalMessage (char *text) |
||
737 | { |
||
738 | if (cls.state == ca_dedicated) |
||
739 | return true; |
||
740 | |||
741 | scr_notifystring = text; |
||
742 | |||
743 | // draw a fresh screen |
||
744 | scr_fullupdate = 0; |
||
745 | scr_drawdialog = true; |
||
746 | SCR_UpdateScreen (); |
||
747 | scr_drawdialog = false; |
||
748 | |||
749 | S_ClearBuffer (); // so dma doesn't loop current sound |
||
750 | |||
751 | do |
||
752 | { |
||
753 | key_count = -1; // wait for a key down and up |
||
754 | Sys_SendKeyEvents (); |
||
755 | } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE); |
||
756 | |||
757 | scr_fullupdate = 0; |
||
758 | SCR_UpdateScreen (); |
||
759 | |||
760 | return key_lastpress == 'y'; |
||
761 | } |
||
762 | |||
763 | |||
764 | //============================================================================= |
||
765 | |||
766 | /* |
||
767 | =============== |
||
768 | SCR_BringDownConsole |
||
769 | |||
770 | Brings the console down and fades the palettes back to normal |
||
771 | ================ |
||
772 | */ |
||
773 | void SCR_BringDownConsole (void) |
||
774 | { |
||
775 | int i; |
||
776 | |||
777 | scr_centertime_off = 0; |
||
778 | |||
779 | for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++) |
||
780 | SCR_UpdateScreen (); |
||
781 | |||
782 | cl.cshifts[0].percent = 0; // no area contents palette on next frame |
||
783 | VID_SetPalette (host_basepal); |
||
784 | } |
||
785 | |||
786 | void SCR_TileClear (void) |
||
787 | { |
||
788 | if (r_refdef.vrect.x > 0) { |
||
789 | // left |
||
790 | Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - sb_lines); |
||
791 | // right |
||
792 | Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, |
||
793 | vid.width - r_refdef.vrect.x + r_refdef.vrect.width, |
||
794 | vid.height - sb_lines); |
||
795 | } |
||
796 | if (r_refdef.vrect.y > 0) { |
||
797 | // top |
||
798 | Draw_TileClear (r_refdef.vrect.x, 0, |
||
799 | r_refdef.vrect.x + r_refdef.vrect.width, |
||
800 | r_refdef.vrect.y); |
||
801 | // bottom |
||
802 | Draw_TileClear (r_refdef.vrect.x, |
||
803 | r_refdef.vrect.y + r_refdef.vrect.height, |
||
804 | r_refdef.vrect.width, |
||
805 | vid.height - sb_lines - |
||
806 | (r_refdef.vrect.height + r_refdef.vrect.y)); |
||
807 | } |
||
808 | } |
||
809 | |||
810 | /* |
||
811 | ================== |
||
812 | SCR_UpdateScreen |
||
813 | |||
814 | This is called every frame, and can also be called explicitly to flush |
||
815 | text to the screen. |
||
816 | |||
817 | WARNING: be very careful calling this from elsewhere, because the refresh |
||
818 | needs almost the entire 256k of stack space! |
||
819 | ================== |
||
820 | */ |
||
821 | void SCR_UpdateScreen (void) |
||
822 | { |
||
823 | static float oldscr_viewsize; |
||
824 | vrect_t vrect; |
||
825 | |||
826 | if (block_drawing) |
||
827 | return; |
||
828 | |||
829 | vid.numpages = 2 + gl_triplebuffer.value; |
||
830 | |||
831 | scr_copytop = 0; |
||
832 | scr_copyeverything = 0; |
||
833 | |||
834 | if (scr_disabled_for_loading) |
||
835 | { |
||
836 | if (realtime - scr_disabled_time > 60) |
||
837 | { |
||
838 | scr_disabled_for_loading = false; |
||
839 | Con_Printf ("load failed.\n"); |
||
840 | } |
||
841 | else |
||
842 | return; |
||
843 | } |
||
844 | |||
845 | if (!scr_initialized || !con_initialized) |
||
846 | return; // not initialized yet |
||
847 | |||
848 | |||
849 | GL_BeginRendering (&glx, &gly, &glwidth, &glheight); |
||
850 | |||
851 | // |
||
852 | // determine size of refresh window |
||
853 | // |
||
854 | if (oldfov != scr_fov.value) |
||
855 | { |
||
856 | oldfov = scr_fov.value; |
||
857 | vid.recalc_refdef = true; |
||
858 | } |
||
859 | |||
860 | if (oldscreensize != scr_viewsize.value) |
||
861 | { |
||
862 | oldscreensize = scr_viewsize.value; |
||
863 | vid.recalc_refdef = true; |
||
864 | } |
||
865 | |||
866 | if (vid.recalc_refdef) |
||
867 | SCR_CalcRefdef (); |
||
868 | |||
869 | // |
||
870 | // do 3D refresh drawing, and then update the screen |
||
871 | // |
||
872 | SCR_SetUpToDrawConsole (); |
||
873 | |||
874 | V_RenderView (); |
||
875 | |||
876 | GL_Set2D (); |
||
877 | |||
878 | // |
||
879 | // draw any areas not covered by the refresh |
||
880 | // |
||
881 | SCR_TileClear (); |
||
882 | |||
883 | if (scr_drawdialog) |
||
884 | { |
||
885 | Sbar_Draw (); |
||
886 | Draw_FadeScreen (); |
||
887 | SCR_DrawNotifyString (); |
||
888 | scr_copyeverything = true; |
||
889 | } |
||
890 | else if (scr_drawloading) |
||
891 | { |
||
892 | SCR_DrawLoading (); |
||
893 | Sbar_Draw (); |
||
894 | } |
||
895 | else if (cl.intermission == 1 && key_dest == key_game) |
||
896 | { |
||
897 | Sbar_IntermissionOverlay (); |
||
898 | } |
||
899 | else if (cl.intermission == 2 && key_dest == key_game) |
||
900 | { |
||
901 | Sbar_FinaleOverlay (); |
||
902 | SCR_CheckDrawCenterString (); |
||
903 | } |
||
904 | else |
||
905 | { |
||
906 | if (crosshair.value) |
||
907 | Draw_Character (scr_vrect.x + scr_vrect.width/2, scr_vrect.y + scr_vrect.height/2, '+'); |
||
908 | |||
909 | SCR_DrawRam (); |
||
910 | SCR_DrawNet (); |
||
911 | SCR_DrawTurtle (); |
||
912 | SCR_DrawPause (); |
||
913 | SCR_CheckDrawCenterString (); |
||
914 | Sbar_Draw (); |
||
915 | SCR_DrawConsole (); |
||
916 | M_Draw (); |
||
917 | } |
||
918 | |||
919 | V_UpdatePalette (); |
||
920 | |||
921 | GL_EndRendering (); |
||
922 | }20>40>=99>>>>>>>>>>>>=>40>=> |
||
923 |