DEADSOFTWARE

gl: do not used max bound texture size automatically
[d2df-sdl.git] / src / game / renders / opengl / r_render.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../../../shared/a_modes.inc}
16 unit r_render;
18 interface
20 uses
21 {$IFDEF ENABLE_MENU}
22 g_gui,
23 {$ENDIF}
24 g_base // TRectWH
25 ;
27 type
28 TProcedure = procedure;
30 (* render startup *)
31 procedure r_Render_Initialize;
32 procedure r_Render_Finalize;
34 (* load globally used textures *)
35 procedure r_Render_Load;
36 procedure r_Render_Free;
38 (* load map specific textures *)
39 procedure r_Render_LoadTextures;
40 procedure r_Render_FreeTextures;
42 procedure r_Render_Reset;
43 procedure r_Render_Update;
44 procedure r_Render_Draw;
46 procedure r_Render_Resize (w, h: Integer);
47 procedure r_Render_Apply;
49 procedure r_Render_RequestScreenShot;
51 {$IFDEF ENABLE_GIBS}
52 function r_Render_GetGibRect (m, id: Integer): TRectWH;
53 {$ENDIF}
55 {$IFDEF ENABLE_GFX}
56 procedure r_Render_QueueEffect (AnimType, X, Y: Integer);
57 {$ENDIF}
59 {$IFDEF ENABLE_TOUCH}
60 // touch screen button location and size
61 procedure r_Render_GetKeyRect (key: Integer; out x, y, w, h: Integer; out founded: Boolean);
62 {$ENDIF}
64 {$IFDEF ENABLE_MENU}
65 procedure r_Render_GetControlSize (ctrl: TGUIControl; out w, h: Integer);
66 procedure r_Render_GetLogoSize (out w, h: Integer);
67 procedure r_Render_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
68 procedure r_Render_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
69 {$ENDIF}
71 procedure r_Render_SetProcessLoadingCallback (p: TProcedure);
72 procedure r_Render_ClearLoading;
73 procedure r_Render_SetLoading (const text: String; maxval: Integer);
74 procedure r_Render_StepLoading (incval: Integer);
75 procedure r_Render_DrawLoading (force: Boolean);
77 {$IFDEF ENABLE_HOLMES}
78 function pmsCurMapX (): Integer;
79 function pmsCurMapY (): Integer;
80 function r_Render_HolmesViewIsSet (): Boolean;
81 {$ENDIF}
83 implementation
85 uses
86 {$I ../../../nogl/noGLuses.inc}
87 Imaging, ImagingTypes, ImagingUtility, (* for screenshots *)
88 {$IFDEF ENABLE_MENU}
89 r_gui,
90 {$ENDIF}
91 {$IFDEF ENABLE_SYSTEM}
92 g_system,
93 {$ENDIF}
94 {$IFDEF ENABLE_TOUCH}
95 r_touch,
96 {$ENDIF}
97 {$IFDEF ENABLE_HOLMES}
98 r_holmes,
99 {$ENDIF}
100 SysUtils, Classes, Math,
101 g_basic,
102 e_sound, // DebugSound
103 e_log, e_res, utils, wadreader, mapdef,
104 g_game, g_map, g_panel, g_options, g_console, g_player, g_weapons, g_language, g_triggers, g_monsters,
105 g_net, g_netmaster,
106 r_draw, r_textures, r_fonts, r_common, r_console, r_map, r_loadscreen
109 var
110 hud, hudbg: TGLTexture;
111 hudhp: array [Boolean] of TGLTexture;
112 hudap: TGLTexture;
113 hudwp: array [0..WP_LAST] of TGLTexture;
114 hudkey: array [0..2] of TGLTexture;
115 hudair: TGLTexture;
116 hudjet: TGLTexture;
117 hudrflag, hudrflags, hudrflagd: TGLTexture;
118 hudbflag, hudbflags, hudbflagd: TGLTexture;
120 FPS, FPSCounter, FPSTime: LongWord;
121 TakeScreenShot: Boolean;
122 DebugSound: Boolean;
124 procedure r_Render_LoadTextures;
125 begin
126 r_Map_LoadTextures;
127 end;
129 procedure r_Render_FreeTextures;
130 begin
131 r_Map_FreeTextures;
132 end;
134 procedure r_Render_Load;
135 const
136 WeapName: array [0..WP_LAST] of AnsiString = ('KASTET', 'SAW', 'PISTOL', 'SHOTGUN1', 'SHOTGUN2', 'MGUN', 'RLAUNCHER', 'PGUN', 'BFG', 'SPULEMET', 'FLAMETHROWER');
137 var
138 i: Integer;
139 begin
140 r_LoadScreen_Load;
141 r_Common_Load;
142 r_Common_SetLoading('HUD Textures', 5 + (WP_LAST + 1) + 11);
143 hud := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/HUD', [TGLHints.txNoRepeat]);
144 hudbg := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/HUDBG', []);
145 hudhp[false] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/MED2', [TGLHints.txNoRepeat]);
146 hudhp[true] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/BMED', [TGLHints.txNoRepeat]);
147 hudap := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/ARMORHUD', [TGLHints.txNoRepeat]);
148 for i := 0 to WP_LAST do
149 hudwp[i] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/' + WeapName[i], [TGLHints.txNoRepeat]);
150 hudkey[0] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/KEYR', [TGLHints.txNoRepeat]);
151 hudkey[1] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/KEYG', [TGLHints.txNoRepeat]);
152 hudkey[2] := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/KEYB', [TGLHints.txNoRepeat]);
153 hudair := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/AIRBAR', [TGLHints.txNoRepeat]);
154 hudjet := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/JETBAR', [TGLHints.txNoRepeat]);
155 hudrflag := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_R_BASE', [TGLHints.txNoRepeat]);
156 hudrflags := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_R_STOLEN', [TGLHints.txNoRepeat]);
157 hudrflagd := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_R_DROP', [TGLHints.txNoRepeat]);
158 hudbflag := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_B_BASE', [TGLHints.txNoRepeat]);
159 hudbflags := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_B_STOLEN', [TGLHints.txNoRepeat]);
160 hudbflagd := r_Common_LoadTextureFromFile(GameWAD + ':TEXTURES/FLAGHUD_B_DROP', [TGLHints.txNoRepeat]);
161 r_Console_Load;
162 r_Map_Load;
163 {$IFDEF ENABLE_MENU}
164 r_GUI_Load;
165 {$ENDIF}
166 end;
168 procedure r_Render_Free;
169 var i: Integer;
170 begin
171 {$IFDEF ENABLE_MENU}
172 r_GUI_Free;
173 {$ENDIF}
174 r_Map_Free;
175 r_Console_Free;
176 r_Common_FreeAndNil(hudbflagd);
177 r_Common_FreeAndNil(hudbflags);
178 r_Common_FreeAndNil(hudbflag);
179 r_Common_FreeAndNil(hudrflagd);
180 r_Common_FreeAndNil(hudrflags);
181 r_Common_FreeAndNil(hudrflag);
182 r_Common_FreeAndNil(hudjet);
183 r_Common_FreeAndNil(hudair);
184 r_Common_FreeAndNil(hudkey[0]);
185 r_Common_FreeAndNil(hudkey[1]);
186 r_Common_FreeAndNil(hudkey[2]);
187 for i := 0 to WP_LAST do
188 r_Common_FreeAndNil(hudwp[i]);
189 r_Common_FreeAndNil(hudap);
190 r_Common_FreeAndNil(hudhp[true]);
191 r_Common_FreeAndNil(hudhp[false]);
192 r_Common_FreeAndNil(hudbg);
193 r_Common_FreeAndNil(hud);
194 r_Common_Free;
195 end;
197 {$IFDEF ENABLE_SYSTEM}
198 function GetInfo (): TGLDisplayInfo;
199 var info: TGLDisplayInfo;
200 begin
201 info := Default(TGLDisplayInfo);
202 info.w := Max(1, gRC_Width);
203 info.h := Max(1, gRC_Height);
204 info.bpp := Max(1, gBPP);
205 info.fullscreen := gRC_FullScreen;
206 info.maximized := gRC_Maximized;
207 info.major := 1;
208 info.minor := 1;
209 {$IFDEF USE_GLES1}
210 info.profile := TGLProfile.Common;
211 {$ELSE}
212 info.profile := TGLProfile.Compat;
213 {$ENDIF}
214 result := info;
215 end;
216 {$ENDIF}
218 procedure r_Render_LogGLInfo;
219 var size: GLint;
220 begin
221 size := 0;
222 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @size);
223 e_LogWritefln('GL Vendor: %s', [glGetString(GL_VENDOR)]);
224 e_LogWritefln('GL Renderer: %s', [glGetString(GL_RENDERER)]);
225 e_LogWritefln('GL Version: %s', [glGetString(GL_VERSION)]);
226 e_LogWritefln('GL Shaders: %s', [glGetString(GL_SHADING_LANGUAGE_VERSION)]);
227 e_LogWritefln('GL Extensions: %s', [glGetString(GL_EXTENSIONS)]);
228 e_LogWritefln('GL Texture: %s', [size]);
229 end;
231 procedure r_Render_Initialize;
232 begin
233 {$IFDEF ENABLE_SYSTEM}
234 if sys_SetDisplayModeGL(GetInfo()) = False then
235 raise Exception.Create('Failed to set videomode on startup.');
236 sys_EnableVSync(gVSync);
237 {$ENDIF}
238 {$IFDEF NOGL_INIT}
239 nogl_Init;
240 {$ENDIF}
241 r_Render_LogGLInfo;
242 r_LoadScreen_Initialize;
243 r_Textures_Initialize;
244 r_Console_Initialize;
245 r_Map_Initialize;
246 end;
248 procedure r_Render_Finalize;
249 begin
250 r_Map_Finalize;
251 r_Console_Finalize;
252 r_Textures_Finalize;
253 r_LoadScreen_Finalize;
254 {$IFDEF NOGL_INIT}
255 nogl_Quit;
256 {$ENDIF}
257 end;
259 procedure r_Render_Reset;
260 begin
261 r_Map_Reset;
262 end;
264 procedure r_Render_Update;
265 begin
266 r_Console_Update;
267 r_Map_Update;
268 end;
270 procedure r_Render_DrawHUD (x, y: Integer; p: TPlayer);
271 var t: TGLTexture; s: AnsiString;
272 begin
273 ASSERT(p <> nil);
275 // hud area is 196 x 240 pixels
276 r_Common_DrawTexture(hud, x, y, hud.width, hud.height, TBasePoint.BP_LEFTUP);
277 r_Common_DrawText(p.name, x + 98, y + 16, 255, 0, 0, 255, smallfont, TBasePoint.BP_CENTER);
279 t := hudhp[R_BERSERK in p.FRulez];
280 r_Common_DrawTexture(t, x + 51, y + 61, t.width, t.height, TBasePoint.BP_CENTER);
281 r_Common_DrawTexture(hudap, x + 50, y + 85, hudap.width, hudap.height, TBasePoint.BP_CENTER);
283 r_Common_DrawText(IntToStr(MAX(0, p.health)), x + 174, y + 56, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
284 r_Common_DrawText(IntToStr(MAX(0, p.armor)), x + 174, y + 84, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
286 case p.CurrWeap of
287 WEAPON_KASTET, WEAPON_SAW: s := '--';
288 else s := IntToStr(p.GetAmmoByWeapon(p.CurrWeap));
289 end;
290 r_Common_DrawText(s, x + 174, y + 174, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
292 if p.CurrWeap <= WP_LAST then
293 begin
294 t := hudwp[p.CurrWeap];
295 r_Common_DrawTexture(t, x + 18, y + 160, t.width, t.height, TBasePoint.BP_LEFTUP);
296 end;
298 if R_KEY_RED in p.FRulez then
299 r_Common_DrawTexture(hudkey[0], x + 76, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
300 if R_KEY_GREEN in p.FRulez then
301 r_Common_DrawTexture(hudkey[1], x + 93, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
302 if R_KEY_BLUE in p.FRulez then
303 r_Common_DrawTexture(hudkey[2], x + 110, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
305 if p.JetFuel > 0 then
306 begin
307 r_Common_DrawTexture(hudair, x, y + 116, hudair.width, hudair.height, TBasePoint.BP_LEFTUP);
308 if p.air > 0 then
309 r_Draw_FillRect(x + 14, y + 116 + 4, x + 14 + 168 * p.air div AIR_MAX, y + 116 + 4 + 4, 0, 0, 196, 255);
310 r_Common_DrawTexture(hudjet, x, y + 126, hudjet.width, hudjet.height, TBasePoint.BP_LEFTUP);
311 r_Draw_FillRect(x + 14, y + 126 + 4, x + 14 + 168 * p.JetFuel div JET_MAX, y + 126 + 4 + 4, 208, 0, 0, 255);
312 end
313 else
314 begin
315 r_Common_DrawTexture(hudair, x, y + 124, hudair.width, hudair.height, TBasePoint.BP_LEFTUP);
316 if p.air > 0 then
317 r_Draw_FillRect(x + 14, y + 124 + 4, x + 14 + 168 * p.air div AIR_MAX, y + 124 + 4 + 4, 0, 0, 196, 255);
318 end;
319 end;
321 procedure r_Render_DrawHUDArea (x, y, w, h: Integer; p: TPlayer);
322 var s: AnsiString; oldy: Integer;
323 begin
324 r_Common_DrawTexture(hudbg, x, y, w, h, TBasePoint.BP_LEFTUP);
326 if p <> nil then
327 begin
328 oldy := y;
329 if h < 239 then y := y - 32; (* hack: hide nickname on 640x400 *)
330 r_Render_DrawHUD(x + w - 196 + 2, y, p);
331 if p.Spectator then
332 begin
333 r_Common_DrawText(_lc[I_PLAYER_SPECT], x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
334 r_Common_DrawText(_lc[I_PLAYER_SPECT2], x + 4, y + 258, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
335 r_Common_DrawText(_lc[I_PLAYER_SPECT1], x + 4, y + 274, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
336 if p.NoRespawn then
337 r_Common_DrawText(_lc[I_PLAYER_SPECT1S], x + 4, y + 290, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
338 end;
339 y := oldy;
340 end;
342 if gShowPing and g_Game_IsClient then
343 begin
344 s := _lc[I_GAME_PING_HUD] + IntToStr(NetPeer.lastRoundTripTime) + _lc[I_NET_SLIST_PING_MS];
345 r_Common_DrawText(s, x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
346 end;
347 end;
349 procedure r_Render_DrawStatsView (x, y, w, h: Integer; p: TPlayer);
350 var fw, i, maxFrags, top, totalPlayers: Integer; sign: Char; stat: TPlayerStatArray; f: TGLTexture;
351 begin
352 ASSERT(p <> nil);
354 if gShowScore and (gGameSettings.GameMode in [GM_TDM, GM_CTF]) then
355 begin
356 (* RED TEAM SCORE *)
357 fw := 0;
358 if gGameSettings.GameMode = GM_CTF then
359 begin
360 case gFlags[FLAG_RED].State of
361 FLAG_STATE_CAPTURED: f := hudrflags;
362 FLAG_STATE_DROPPED: f := hudrflagd;
363 otherwise f := hudrflag;
364 end;
365 if f <> nil then
366 begin
367 fw := f.width + 8; (* + space *)
368 r_Common_DrawTexture(f, x + w - 16, y + 240 - 72 - 4, f.width, f.height, TBasePoint.BP_RIGHTUP);
369 end;
370 end;
371 r_Common_DrawText(IntToStr(gTeamStat[TEAM_RED].Score), x + w - 16 - fw, y + 240 - 72 - 4, TEAMCOLOR[TEAM_RED].R, TEAMCOLOR[TEAM_RED].G, TEAMCOLOR[TEAM_RED].B, 255, menufont, TBasePoint.BP_RIGHTUP);
373 (* BLUE TEAM SCORE *)
374 fw := 0;
375 if gGameSettings.GameMode = GM_CTF then
376 begin
377 case gFlags[FLAG_BLUE].State of
378 FLAG_STATE_CAPTURED: f := hudbflags;
379 FLAG_STATE_DROPPED: f := hudbflagd;
380 otherwise f := hudbflag;
381 end;
382 if f <> nil then
383 begin
384 fw := f.width + 8; (* + space *)
385 r_Common_DrawTexture(f, x + w - 16, y + 240 - 32 - 4, f.width, f.height, TBasePoint.BP_RIGHTUP);
386 end;
387 end;
388 r_Common_DrawText(IntToStr(gTeamStat[TEAM_BLUE].Score), x + w - 16 - fw, y + 240 - 32 - 4, TEAMCOLOR[TEAM_BLUE].R, TEAMCOLOR[TEAM_BLUE].G, TEAMCOLOR[TEAM_BLUE].B, 255, menufont, TBasePoint.BP_RIGHTUP);
389 end;
391 if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
392 begin
393 if gShowStat then
394 begin
395 r_Common_DrawText(IntToStr(p.Frags), x + w - 16, y, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHTUP);
397 top := 1;
398 maxFrags := 0;
399 totalPlayers := 0;
400 stat := g_Player_GetStats();
401 if stat <> nil then
402 begin
403 totalPlayers := Length(stat);
404 for i := 0 to High(stat) do
405 begin
406 if stat[i].Name <> p.Name then
407 begin
408 maxFrags := MAX(maxFrags, stat[i].Frags);
409 if stat[i].Frags > p.Frags then
410 top := top + 1;
411 end;
412 end;
413 end;
414 if p.Frags >= maxFrags then sign := '+' else sign := '-';
415 r_Common_DrawText(IntToStr(top) + ' / ' + IntToStr(totalPlayers) + ' ' + sign + IntToStr(ABS(p.Frags - maxFrags)), x + w - 16, y + 32, 255, 0, 0, 255, smallfont, TBasePoint.BP_RIGHTUP);
416 end;
418 if gLMSRespawn > LMS_RESPAWN_NONE then
419 begin
420 r_Common_DrawText(_lc[I_GAME_WARMUP], x + w - 16 - 64, y + h, 0, 255, 0, 255, menufont, TBasePoint.BP_RIGHTDOWN);
421 r_Common_DrawText(': ' + IntToStr((gLMSRespawnTime - gTime) div 1000), x + w - 16 - 64, y + h, 0, 255, 0, 255, menufont, TBasePoint.BP_LEFTDOWN);
422 end
423 else if gShowLives and (gGameSettings.MaxLives > 0) then
424 begin
425 r_Common_DrawText(IntToStr(p.Lives), x + w - 16, y + h, 0, 255, 0, 255, menufont, TBasePoint.BP_RIGHTDOWN);
426 end;
427 end;
428 end;
430 procedure r_Render_DrawView (x, y, w, h: Integer; p: TPlayer);
431 var l, t, r, b, xx, yy, cx, cy: Integer;
432 begin
433 r_Draw_GetRect(l, t, r, b);
434 r_Draw_SetRect(x, y, x + w, y + h);
436 r_Common_GetCameraPos(p, true, xx, yy);
437 if p <> nil then
438 begin
439 r_Map_Draw(x, y, w, h, xx, yy, p, cx, cy);
440 {$IFDEF ENABLE_HOLMES}
441 if p = gPlayer1 then
442 begin
443 r_Holmes_plrViewPos(cx, cy);
444 r_Holmes_plrViewSize(h, w);
445 end;
446 {$ENDIF}
447 r_Render_DrawStatsView(x, y, w, h, p);
448 if p.Spectator and p.NoRespawn then
449 r_Common_DrawText(_lc[I_PLAYER_SPECT4], x div 2 + w div 2, y div 2 + h div 2, 255, 255, 255, 255, stdfont, TBasePoint.BP_CENTER);
450 end
451 else
452 begin
453 r_Map_Draw(x, y, w, h, xx, yy, nil, cx, cy);
454 end;
456 r_Draw_SetRect(l, t, r, b);
457 end;
459 procedure r_Render_DrawMapView (x, y, w, h, camx, camy: Integer);
460 var l, t, r, b, cx, cy: Integer;
461 begin
462 r_Draw_GetRect(l, t, r, b);
463 r_Draw_SetRect(x, y, x + w, y + h);
464 r_Map_Draw(x, y, w, h, camx, camy, nil, cx, cy);
465 r_Draw_SetRect(l, t, r, b);
466 end;
468 procedure r_Render_DrawPlayerView (x, y, w, h: Integer; p: TPlayer);
469 var l, t, r, b: Integer;
470 begin
471 r_Draw_GetRect(l, t, r, b);
472 r_Draw_SetRect(x, y, x + w, y + h);
473 r_Render_DrawView(x, y, w - 196, h, p);
474 r_Render_DrawHUDArea(x + w - 196, y, 196, h, p);
475 r_Draw_SetRect(l, t, r, b);
476 end;
478 procedure r_Render_DrawServerList (var SL: TNetServerList; var ST: TNetServerTable);
479 var ip: AnsiString; ww, hh, cw, ch, mw, mh, motdh, scrx, scry, i, mx, y: Integer; msg: SSArray; Srv: TNetServer;
480 begin
481 scrx := gScreenWidth div 2;
482 scry := gScreenHeight div 2;
484 r_Draw_GetTextSize(_lc[I_NET_SLIST], menufont, ww, hh);
485 r_Common_DrawText(_lc[I_NET_SLIST], gScreenWidth div 2, 16, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
487 r_Draw_GetTextSize('W', stdfont, cw, ch);
488 motdh := gScreenHeight - 49 - ch * b_Text_LineCount(slMOTD);
490 (* window background *)
491 r_Draw_Rect(16, 64, gScreenWidth - 16, motdh + 1, 255, 127, 0, 255);
492 r_Draw_FillRect(16 + 1, 64 + 1, gScreenWidth - 16 - 1, motdh, 64, 64, 64, 145);
494 r_Common_DrawText(_lc[I_NET_SLIST_HELP], gScreenWidth div 2, gScreenHeight - 8, 255, 255, 255, 255, stdfont, TBasePoint.BP_DOWN);
496 if slMOTD <> '' then
497 begin
498 r_Draw_Rect(16, motdh, gScreenWidth - 16, gScreenHeight - 44, 255, 127, 0, 255);
499 r_Draw_FillRect(16 + 1, motdh + 1, gScreenWidth - 16 - 1, gScreenHeight - 44 - 1, 64, 64, 64, 145);
500 r_Common_DrawFormatText(slMOTD, 20, motdh + 3, 255, stdfont, TBasePoint.BP_LEFTUP);
501 end;
503 if not slReadUrgent and (slUrgent <> '') then
504 begin
505 r_Draw_Rect(scrx - 256, scry - 60, scrx + 256, scry + 60 + 1, 255, 127, 0, 255);
506 r_Draw_FillRect(scrx - 256 + 1, scry - 60 + 1, scrx + 256 - 1, scry + 60, 64, 64, 64, 127);
507 r_Draw_FillRect(scrx - 256, scry - 40, scrx + 256, scry - 40 + 1, 255, 127, 0, 255);
508 r_Draw_FillRect(scrx - 256, scry + 40, scrx + 256, scry + 40 + 1, 255, 127, 0, 255);
509 r_Common_DrawText(_lc[I_NET_SLIST_URGENT], scrx, scry - 58, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
510 r_Common_DrawText(_lc[I_NET_SLIST_URGENT_CONT], scrx, scry + 41, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
511 r_Common_DrawFormatText(slUrgent, scrx - 253, scry - 38, 255, stdfont, TBasePoint.BP_LEFTUP);
512 end
513 else if SL = nil then
514 begin
515 r_Draw_Rect(scrx - 192, scry - 10, scrx + 192, scry + 10, 255, 127, 0, 255);
516 r_Draw_FillRect(scrx - 192 + 1, scry - 10 + 1, scrx + 192 - 1, scry + 10 - 1, 64, 64, 64, 145);
517 r_Common_DrawText(slWaitStr, scrx, scry, 255, 255, 255, 255, stdfont, TBasePoint.BP_CENTER);
518 end
519 else
520 begin
521 y := 90;
522 if slSelection < Length(ST) then
523 begin
524 sy := y + 42 * slSelection - 4;
525 Srv := GetServerFromTable(slSelection, SL, ST);
526 ip := _lc[I_NET_ADDRESS] + ' ' + Srv.IP + ':' + IntToStr(Srv.Port);
527 ip := ip + ' ' + _lc[I_NET_SERVER_PASSWORD] + ' ';
528 if Srv.Password then ip := ip + _lc[I_MENU_YES] else ip := ip +_lc[I_MENU_NO];
529 end;
531 mw := gScreenWidth - 188;
532 mx := 16 + mw;
534 (* current selection *)
535 r_Draw_FillRect(16 + 1, sy + 1, gScreenWidth - 16 - 1, sy + 1 + 40, 64, 64, 64, 255);
536 r_Draw_FillRect(16 + 1, sy, gScreenWidth - 16 - 1, sy + 1, 255, 255, 255, 255);
537 r_Draw_FillRect(16 + 1, sy + 1 + 40, gScreenWidth - 16 - 1, sy + 1 + 40 + 1, 255, 255, 255, 255);
539 (* line separators for name/ping/mode.. & address/pasword *)
540 r_Draw_FillRect(16, 85, gScreenWidth - 16, 85 + 1, 255, 127, 0, 255);
541 r_Draw_FillRect(16, motdh - 20, gScreenWidth - 16, motdh - 20 + 1, 255, 127, 0, 255);
543 (* column separators for name/ping/mode/players/version *)
544 r_Draw_FillRect(mx - 70, 64 + 1, mx - 70 + 1, motdh, 255, 127, 0, 255);
545 r_Draw_FillRect(mx, 64 + 1, mx + 1, motdh - 20, 255, 127, 0, 255);
546 r_Draw_FillRect(mx + 52, 64 + 1, mx + 52 + 1, motdh - 20, 255, 127, 0, 255);
547 r_Draw_FillRect(mx + 104, 64 + 1, mx + 104 + 1, motdh - 20, 255, 127, 0, 255);
549 r_Common_DrawText('NAME/MAP', 18, 68, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
550 r_Common_DrawText('PING', mx - 68, 68, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
551 r_Common_DrawText('MODE', mx + 2, 68, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
552 r_Common_DrawText('PLRS', mx + 54, 68, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
553 r_Common_DrawText('VER', mx + 106, 68, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
555 for i := 0 to High(ST) do
556 begin
557 Srv := GetServerFromTable(i, SL, ST);
558 r_Common_DrawText(Srv.Name, 18, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
559 r_Common_DrawText(Srv.Map, 18, y + 16, 210, 210, 210, 255, stdfont, TBasePoint.BP_LEFTUP);
561 if Srv.Ping = 0 then
562 r_Common_DrawText('<1' + _lc[I_NET_SLIST_PING_MS], mx - 68, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP)
563 else if (Srv.Ping >= 0) and (Srv.Ping <= 999) then
564 r_Common_DrawText(IntToStr(Srv.Ping) + _lc[I_NET_SLIST_PING_MS], mx - 68, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP)
565 else
566 r_Common_DrawText(_lc[I_NET_SLIST_NO_ACCESS], mx - 68, y, 255, 0, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
567 if Length(ST[I].Indices) > 1 then
568 r_Common_DrawText('<' + IntToStr(Length(ST[I].Indices)) + '>', mx - 68, y + 16, 210, 210, 210, 255, stdfont, TBasePoint.BP_LEFTUP);
570 r_Common_DrawText(g_Game_ModeToText(Srv.GameMode), mx + 2, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
572 r_Common_DrawText(IntToStr(Srv.Players) + '/' + IntToStr(Srv.MaxPlayers), mx + 54, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
573 r_Common_DrawText(IntToStr(Srv.LocalPl) + '+' + IntToStr(Srv.Bots), mx + 54, y + 16, 210, 210, 210, 255, stdfont, TBasePoint.BP_LEFTUP);
575 r_Common_DrawText(IntToStr(Srv.Protocol), mx + 106, y, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
577 y := y + 42;
578 end;
580 r_Common_DrawText(ip, 20, motdh - 20 + 3, 205, 205, 205, 255, stdfont, TBasePoint.BP_LEFTUP);
581 r_Common_DrawText(IntToStr(Length(ST)) + _lc[I_NET_SLIST_SERVERS], gScreenWidth - 48, motdh - 20 + 3, 255, 255, 255, 255, stdfont, TBasePoint.BP_RIGHTUP);
582 end;
583 end;
585 procedure r_Render_DrawStatsColumns (constref cs: TEndCustomGameStat; x, y, w: Integer; endview: Boolean);
586 var i, cw, ch, yy, team, players, w1, w2, w3, w4, tw: Integer; r, g, b, rr, gg, bb: Byte; s: AnsiString;
587 begin
588 r_Draw_GetTextSize('W', stdfont, cw, ch);
589 w4 := cw * 6; (* deaths width *)
590 w3 := cw * 8; (* frags width *)
591 w2 := cw * 12; (* ping/loss width *)
592 w1 := w - w2 - w3 - w4; (* name width *)
593 tw := w1 - cw * 2 - w2; (* team score *)
594 if cs.PlayerStat = nil then players := 0 else players := Length(cs.PlayerStat);
595 yy := y;
596 if cs.GameMode in [GM_TDM, GM_CTF] then
597 begin
598 for team := TEAM_RED to TEAM_BLUE do
599 begin
600 case team of
601 TEAM_RED:
602 begin
603 s := _lc[I_GAME_TEAM_RED];
604 r := 255; g := 0; b := 0;
605 end;
606 TEAM_BLUE:
607 begin
608 s := _lc[I_GAME_TEAM_BLUE];
609 r := 0; g := 0; b := 255;
610 end;
611 end;
612 r_Common_DrawText(s, x, yy, r, g, b, 255, stdfont, TBasePoint.BP_LEFTUP);
613 r_Common_DrawText(IntToStr(cs.TeamStat[team].Score), x + tw, yy, r, g, b, 255, stdfont, TBasePoint.BP_UP);
614 if endview = false then
615 r_Common_DrawText(_lc[I_GAME_PING], x + w1, yy, r, g, b, 255, stdfont, TBasePoint.BP_UP);
616 r_Common_DrawText(_lc[I_GAME_FRAGS], x + w1 + w2, yy, r, g, b, 255, stdfont, TBasePoint.BP_UP);
617 r_Common_DrawText(_lc[I_GAME_DEATHS], x + w1 + w2 + w3, yy, r, g, b, 255, stdfont, TBasePoint.BP_UP);
618 INC(yy, ch);
620 INC(yy, ch div 4);
621 r_Draw_FillRect(x, yy, x + w, yy + 1, r, g, b, 255);
622 INC(yy, ch div 4);
624 for i := 0 to players - 1 do
625 begin
626 if cs.PlayerStat[i].Team = team then
627 begin
628 rr := r; gg := g; bb := b;
629 if cs.PlayerStat[i].Spectator then
630 begin
631 rr := r div 2; gg := g div 2; bb := b div 2;
632 end;
634 // Player name
635 if gShowPIDs then s := Format('[%5d] %s', [cs.PlayerStat[i].UID, cs.PlayerStat[i].Name]) else s := cs.PlayerStat[i].Name;
636 if (gPlayers[cs.PlayerStat[i].Num] <> nil) and (gPlayers[cs.PlayerStat[i].Num].FReady) then s := s + ' *';
637 r_Common_DrawText(s, x, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_LEFTUP);
638 if endview = false then
639 begin
640 // Player ping/loss
641 s := Format(_lc[I_GAME_PING_MS], [cs.PlayerStat[i].Ping, cs.PlayerStat[i].Loss]);
642 r_Common_DrawText(s, x + w1, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
643 end;
644 // Player frags
645 s := IntToStr(cs.PlayerStat[i].Frags);
646 r_Common_DrawText(s, x + w1 + w2, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
647 // Player deaths
648 s := IntToStr(cs.PlayerStat[i].Deaths);
649 r_Common_DrawText(s, x + w1 + w2 + w3, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
651 INC(yy, ch);
652 end;
653 end;
654 INC(yy, ch);
655 end;
656 end
657 else if cs.GameMode in [GM_DM, GM_COOP] then
658 begin
659 r_Common_DrawText(_lc[I_GAME_PLAYER_NAME], x, yy, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
660 if endview = false then
661 r_Common_DrawText(_lc[I_GAME_PING], x + w1, yy, 255, 127, 0, 255, stdfont, TBasePoint.BP_UP);
662 r_Common_DrawText(_lc[I_GAME_FRAGS], x + w1 + w2, yy, 255, 127, 0, 255, stdfont, TBasePoint.BP_UP);
663 r_Common_DrawText(_lc[I_GAME_DEATHS], x + w1 + w2 + w3, yy, 255, 127, 0, 255, stdfont, TBasePoint.BP_UP);
664 INC(yy, ch + ch div 2);
665 for i := 0 to players - 1 do
666 begin
667 // rr := 255; gg := 127; bb := 0;
668 rr := 255; gg := 255; bb := 255;
669 if cs.PlayerStat[i].Spectator then
670 begin
671 rr := rr div 2; gg := gg div 2; bb := bb div 2;
672 end;
674 // Player color
675 r_Draw_Rect(x, yy, x + 16, yy + 16, 192, 192, 192, 255);
676 r_Draw_FillRect(x + 1, yy + 1, x + 16 - 1, yy + 16 - 1, cs.PlayerStat[i].Color.R, cs.PlayerStat[i].Color.G, cs.PlayerStat[i].Color.B, 255);
677 // Player name
678 if gShowPIDs then s := Format('[%5d] %s', [cs.PlayerStat[i].UID, cs.PlayerStat[i].Name]) else s := cs.PlayerStat[i].Name;
679 if (gPlayers[cs.PlayerStat[i].Num] <> nil) and (gPlayers[cs.PlayerStat[i].Num].FReady) then s := s + ' *';
680 r_Common_DrawText(s, x + 16 + 8, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_LEFTUP);
681 if endview = false then
682 begin
683 // Player ping/loss
684 s := Format(_lc[I_GAME_PING_MS], [cs.PlayerStat[i].Ping, cs.PlayerStat[i].Loss]);
685 r_Common_DrawText(s, x + w1, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
686 end;
687 // Player frags
688 s := IntToStr(cs.PlayerStat[i].Frags);
689 r_Common_DrawText(s, x + w1 + w2, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
690 // Player deaths
691 s := IntToStr(cs.PlayerStat[i].Deaths);
692 r_Common_DrawText(s, x + w1 + w2 + w3, yy, rr, gg, bb, 255, stdfont, TBasePoint.BP_UP);
694 INC(yy, ch + ch div 2);
695 end;
696 end;
697 end;
699 procedure r_Render_DrawStatsWindow (x, y, w, h: Integer; cs: TEndCustomGameStat; endview: Boolean);
700 var xoff, yoff, cw, ch: Integer; s: AnsiString;
701 begin
702 xoff := 0; yoff := 8;
703 r_Draw_GetTextSize('W', stdfont, cw, ch);
704 r_Draw_Rect(x, y, x + w, y + h, 255, 127, 0, 255);
705 r_Draw_FillRect(x + 1, y + 1, x + w - 1, y + h - 1, 64, 64, 64, 224);
707 (* LINE 1 *)
709 if endview = false then
710 begin
711 case NetMode of
712 NET_SERVER: s := _lc[I_NET_SERVER];
713 NET_CLIENT: s := NetClientIP + ':' + IntToStr(NetClientPort);
714 otherwise s := '';
715 end;
716 r_Common_DrawText(s, x + 16, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
717 end;
719 case cs.GameMode of
720 GM_DM: if gGameSettings.MaxLives = 0 then s := _lc[I_GAME_DM] else s := _lc[I_GAME_LMS];
721 GM_TDM: if gGameSettings.MaxLives = 0 then s := _lc[I_GAME_TDM] else s := _lc[I_GAME_TLMS];
722 GM_CTF: s := _lc[I_GAME_CTF];
723 GM_COOP: if gGameSettings.MaxLives = 0 then s := _lc[I_GAME_COOP] else s := _lc[I_GAME_SURV];
724 otherwise s := 'GAME MODE ' + IntToStr(gGameSettings.GameMode);
725 end;
726 r_Common_DrawText(s, x + w div 2, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
728 if endview = false then
729 begin
730 s := r_Common_TimeToStr(cs.GameTime);
731 r_Common_DrawText(s, x + w - 16, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_RIGHTUP);
732 end;
734 INC(yoff, ch + ch div 2);
736 (* LINE 2/3 *)
738 s := cs.Map;
739 if cs.MapName <> '' then
740 s := s + ' - ' + cs.MapName;
742 if endview = false then
743 begin
744 r_Common_DrawText(s, x + w div 2, y + yoff, 200, 200, 200, 255, stdfont, TBasePoint.BP_UP);
745 INC(yoff, ch + ch div 2);
746 case cs.GameMode of
747 GM_DM, GM_TDM: s := Format(_lc[I_GAME_FRAG_LIMIT], [gGameSettings.ScoreLimit]);
748 GM_CTF: s := Format(_lc[I_GAME_SCORE_LIMIT], [gGameSettings.ScoreLimit]);
749 GM_COOP: s := _lc[I_GAME_MONSTERS] + ' ' + IntToStr(gCoopMonstersKilled) + '/' + IntToStr(gTotalMonsters);
750 otherwise s := '';
751 end;
752 r_Common_DrawText(s, x + 16, y + yoff, 200, 200, 200, 255, stdfont, TBasePoint.BP_LEFTUP);
753 case cs.GameMode of
754 GM_DM, GM_TDM, GM_CTF: s := Format(_lc[I_GAME_TIME_LIMIT], [gGameSettings.TimeLimit div 3600, (gGameSettings.TimeLimit div 60) mod 60, gGameSettings.TimeLimit mod 60]);
755 GM_COOP: s := _lc[I_GAME_SECRETS] + ' ' + IntToStr(gCoopSecretsFound) + '/' + IntToStr(gSecretsCount);
756 otherwise s := '';
757 end;
758 r_Common_DrawText(s, x + w - 16, y + yoff, 200, 200, 200, 255, stdfont, TBasePoint.BP_RIGHTUP);
759 INC(yoff, ch);
760 end
761 else
762 begin
763 xoff := MAX(Length(_lc[I_MENU_MAP]) + 1, Length(_lc[I_GAME_GAME_TIME]) + 1) * cw;
764 r_Common_DrawText(_lc[I_MENU_MAP], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
765 r_Common_DrawText(s, x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
766 INC(yoff, ch);
767 r_Common_DrawText(_lc[I_GAME_GAME_TIME], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
768 r_Common_DrawText(r_Common_TimeToStr(cs.GameTime), x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
769 INC(yoff, ch);
770 end;
772 INC(yoff, ch);
774 (* LINE 4/5 *)
776 if endview and (cs.GameMode = GM_COOP) then
777 begin
778 xoff := MAX(Length(_lc[I_GAME_MONSTERS]) + 1, Length(_lc[I_GAME_SECRETS]) + 1) * cw;
779 r_Common_DrawText(_lc[I_GAME_MONSTERS], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
780 r_Common_DrawText(IntToStr(gCoopMonstersKilled) + '/' + IntToStr(gTotalMonsters), x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
781 INC(yoff, ch);
782 r_Common_DrawText(_lc[I_GAME_SECRETS], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
783 r_Common_DrawText(IntToStr(gCoopSecretsFound) + '/' + IntToStr(gSecretsCount), x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
784 INC(yoff, ch);
785 INC(yoff, ch);
786 end;
788 (* LINE 6/7 *)
790 if endview and (cs.GameMode = GM_COOP) and gLastMap then
791 begin
792 xoff := MAX(Length(_lc[I_GAME_MONSTERS_TOTAL]) + 1, Length(_lc[I_GAME_SECRETS_TOTAL]) + 1) * cw;
793 r_Common_DrawText(_lc[I_GAME_MONSTERS_TOTAL], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
794 r_Common_DrawText(IntToStr(gCoopTotalMonstersKilled) + '/' + IntToStr(gCoopTotalMonsters), x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
795 INC(yoff, ch);
796 r_Common_DrawText(_lc[I_GAME_SECRETS_TOTAL], x + 16, y + yoff, 255, 127, 0, 255, stdfont, TBasePoint.BP_LEFTUP);
797 r_Common_DrawText(IntToStr(gCoopTotalSecretsFound) + '/' + IntToStr(gCoopTotalSecrets), x + 16 + xoff, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
798 INC(yoff, ch);
799 INC(yoff, ch);
800 end;
802 (* LINE *)
804 if endview and (cs.GameMode in [GM_TDM, GM_CTF]) then
805 begin
806 if cs.TeamStat[TEAM_RED].Score > cs.TeamStat[TEAM_BLUE].Score then s := _lc[I_GAME_WIN_RED]
807 else if cs.TeamStat[TEAM_BLUE].Score > cs.TeamStat[TEAM_RED].Score then s := _lc[I_GAME_WIN_BLUE]
808 else s := _lc[I_GAME_WIN_DRAW];
809 r_Common_DrawText(s, x + w div 2, y + yoff, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
810 INC(yoff, ch);
811 INC(yoff, ch);
812 end;
814 (* LINE n *)
816 r_Render_DrawStatsColumns(cs, x + 16, y + yoff, w - 16 - 16, endview);
817 end;
819 function r_Render_StatsHeight (players: Integer): Integer;
820 var cw, ch: Integer;
821 begin
822 ASSERT(players >= 0);
823 r_Draw_GetTextSize('W', stdfont, cw, ch);
824 case gGameSettings.GameMode of
825 GM_TDM, GM_CTF: result := 32 + ch * (11 + players);
826 otherwise result := 40 + ch * 5 + (ch + 8) * players;
827 end;
828 end;
830 procedure r_Render_DrawStats;
831 var x, y, w, h, players: Integer; cs: TEndCustomGameStat;
832 begin
833 cs.PlayerStat := g_Player_GetStats();
834 SortGameStat(cs.PlayerStat);
835 cs.TeamStat := gTeamStat;
836 cs.GameTime := gTime;
837 cs.GameMode := gGameSettings.GameMode;
838 cs.Map := g_ExtractWadNameNoPath(gMapInfo.Map) + ':' + g_ExtractFileName(gMapInfo.Map);
839 cs.MapName := gMapInfo.Name;
840 if cs.PlayerStat = nil then players := 0 else players := Length(cs.PlayerStat);
841 w := gScreenWidth - (gScreenWidth div 5);
842 h := r_Render_StatsHeight(players);
843 x := (gScreenWidth div 2) - (w div 2);
844 y := (gScreenHeight div 2) - (h div 2);
845 r_Render_DrawStatsWindow(x, y, w, h, cs, false);
846 end;
848 procedure r_Render_DrawCustomStats;
849 var cw, ch, s: AnsiString;
850 begin
851 if gStatsOff then
852 begin
853 r_Common_DrawText(_lc[I_MENU_INTER_NOTICE_TAB], gScreenWidth div 2, 8, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
854 end
855 else
856 begin
857 case gGameSettings.GameMode of
858 GM_COOP: if gMissionFailed then s := _lc[I_MENU_INTER_MISSION_FAIL] else s := _lc[I_MENU_INTER_LEVEL_COMPLETE];
859 otherwise s := _lc[I_MENU_INTER_ROUND_OVER];
860 end;
861 r_Common_DrawText(s, gScreenWidth div 2, 16, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
863 if gChatShow = false then
864 begin
865 if g_Game_IsClient then s := _lc[I_MENU_INTER_NOTICE_MAP] else s := _lc[I_MENU_INTER_NOTICE_SPACE];
866 r_Common_DrawText(s, gScreenWidth div 2, gScreenHeight - 4, 255, 255, 255, 255, stdfont, TBasePoint.BP_DOWN);
867 if g_Game_IsNet then
868 begin
869 s := Format(_lc[I_MENU_INTER_NOTICE_TIME], [gServInterTime]);
870 r_Common_DrawText(s, gScreenWidth div 2, gScreenHeight - 16 - 4, 255, 255, 255, 255, stdfont, TBasePoint.BP_DOWN);
871 end;
872 end;
874 r_Render_DrawStatsWindow(32, 64, gScreenWidth - 32 * 2, gScreenHeight - 64 * 2, CustomStat, true);
875 end;
876 end;
878 procedure r_Render_DrawValueOf (a, b, x, y: Integer; f: TGLFont);
879 var wa, wb, ch: Integer; sa, sb: AnsiString;
880 begin
881 sa := IntToStr(a);
882 sb := IntToStr(b);
883 r_Draw_GetTextSize(sa, f, wa, ch);
884 r_Draw_GetTextSize(sa + ' / ', f, wb, ch);
885 r_Common_DrawText(sa, x, y, 255, 0, 0, 255, f, TBasePoint.BP_LEFTUP);
886 r_Common_DrawText(' / ', x + wa, y, 255, 255, 255, 255, f, TBasePoint.BP_LEFTUP);
887 r_Common_DrawText(sb, x + wb, y, 255, 0, 0, 255, f, TBasePoint.BP_LEFTUP);
888 end;
890 procedure r_Render_DrawSinglStatsPlayer (player, x, y, w1: Integer);
891 var time, kpm: Single;
892 begin
893 r_Common_DrawText(_lc[I_MENU_INTER_KILLS], x, y, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
894 r_Render_DrawValueOf(SingleStat.PlayerStat[player].Kills, gTotalMonsters, x + w1, y, MenuFont);
895 r_Common_DrawText(_lc[I_MENU_INTER_KPM], x, y + 32, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
896 time := SingleStat.GameTime / 1000;
897 kpm := SingleStat.PlayerStat[player].Kills;
898 if time > 0 then kpm := kpm / time * 60;
899 r_Common_DrawText(Format('%.1f', [kpm]), x + w1, y + 32, 255, 0, 0, 255, menufont, TBasePoint.BP_LEFTUP);
900 r_Common_DrawText(_lc[I_MENU_INTER_SECRETS], x, y + 64, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
901 r_Render_DrawValueOf(SingleStat.PlayerStat[player].Secrets, SingleStat.TotalSecrets, x + w1, y + 64, MenuFont);
902 end;
904 procedure r_Render_DrawSingleStats;
905 var xx, wa, wb, ww, ch: Integer; s: AnsiString;
906 begin
907 r_Common_DrawText(_lc[I_MENU_INTER_LEVEL_COMPLETE], gScreenWidth div 2, 32, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
909 r_Draw_GetTextSize(_lc[I_MENU_INTER_KPM] + ' ', menufont, wa, ch);
910 r_Draw_GetTextSize(' 9999.9', menufont, wb, ch);
911 ww := wa + wb;
912 xx := gScreenWidth div 2 - ww div 2;
914 s := r_Common_TimeToStr(SingleStat.GameTime);
915 r_Common_DrawText(_lc[I_MENU_INTER_TIME], xx, 80, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
916 r_Common_DrawText(s, xx + wa, 80, 255, 0, 0, 255, menufont, TBasePoint.BP_LEFTUP);
918 if SingleStat.TwoPlayers then
919 begin
920 r_Common_DrawText(_lc[I_MENU_PLAYER_1], gScreenWidth div 2, 128, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
921 r_Render_DrawSinglStatsPlayer(0, xx, 176, wa);
922 r_Common_DrawText(_lc[I_MENU_PLAYER_2], gScreenWidth div 2, 288, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
923 r_Render_DrawSinglStatsPlayer(1, xx, 336, wa);
924 end
925 else
926 begin
927 r_Render_DrawSinglStatsPlayer(0, xx, 128, wa);
928 end;
929 end;
931 procedure r_Render_DrawSpectHud;
932 var xoff: Integer; s: AnsiString;
934 procedure AddText (s1, s2: AnsiString);
935 var w1, w2, ww, ch: Integer;
936 begin
937 r_Draw_GetTextSize(s1, stdfont, w1, ch);
938 r_Draw_GetTextSize(s2, stdfont, w2, ch);
939 ww := MAX(w1, w2);
940 r_Common_DrawText(s1, xoff + ww div 2, gScreenHeight - ch, 255, 255, 255, 255, stdfont, TBasePoint.BP_DOWN);
941 r_Common_DrawText(s2, xoff + ww div 2, gScreenHeight - ch, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
942 xoff := xoff + ww + 16;
943 end;
945 begin
946 xoff := 0;
947 case gSpectMode of
948 SPECT_STATS: s := 'MODE: Stats';
949 SPECT_MAPVIEW: s := 'MODE: Observe Map';
950 SPECT_PLAYERS: s := 'MODE: Watch Players';
951 otherwise s := 'MODE: ' + IntToStr(gSpectMode);
952 end;
953 AddText(s, '< jump >');
954 if gSpectMode = SPECT_STATS then
955 AddText('Autoview', '< fire >');
956 if gSpectMode = SPECT_MAPVIEW then
957 AddText('[-] Step ' + IntToStr(gSpectStep) + ' [+]', '<prev weap> <next weap>');
958 if gSpectMode = SPECT_PLAYERS then
959 begin
960 AddText('Player 1', '<left/right>');
961 if gSpectViewTwo then
962 AddText('Player 2', '<prev w/next w>');
963 AddText('2x View', '<up/down>');
964 end;
965 end;
967 function GetActivePlayer_ByID (id: Integer): TPlayer;
968 var i, len: Integer; p: TPlayer;
969 begin
970 p := nil;
971 if (id >= 0) and (gPlayers <> nil) then
972 begin
973 i := 0; len := Length(gPlayers);
974 while (i < len) and ((IsActivePlayer(gPlayers[i]) = false) or (gPlayers[i].UID <> id)) do INC(i);
975 if i < len then p := gPlayers[i];
976 end;
977 result := p;
978 end;
980 procedure r_Render_DrawMinimap (x, y: Integer; alpha: Byte);
981 const scale = 16;
983 function IsMinimapPanel (const p: TPanel): Boolean;
984 begin
985 result := (p <> nil) and p.Enabled;
986 if result then
987 begin
988 case p.PanelType of
989 PANEL_WALL, PANEL_WATER, PANEL_ACID1, PANEL_ACID2,
990 PANEL_STEP, PANEL_OPENDOOR, PANEL_CLOSEDOOR,
991 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT:
992 result := true;
993 otherwise
994 result := false;
995 end;
996 end;
997 end;
999 procedure DrawObject (xx, yy, ww, hh: Integer; r, g, b: Byte);
1000 var x0, y0, x1, y1: Integer;
1001 begin
1002 x0 := x + xx div scale;
1003 y0 := y + yy div scale;
1004 x1 := x + (xx + ww) div scale;
1005 y1 := y + (yy + hh) div scale;
1006 r_Draw_FillRect(x0, y0, x1, y1, r, g, b, alpha);
1007 end;
1009 procedure DrawPanels (const a: TPanelArray);
1010 var i: Integer; p: TPanel; c: TRGB;
1011 begin
1012 if a <> nil then
1013 begin
1014 for i := 0 to HIGH(a) do
1015 begin
1016 p := a[i];
1017 if IsMinimapPanel(p) then
1018 begin
1019 case p.PanelType of
1020 PANEL_WALL: c := _RGB(208, 208, 208);
1021 PANEL_OPENDOOR: c := _RGB(160, 160, 160);
1022 PANEL_CLOSEDOOR: c := _RGB(160, 160, 160);
1023 PANEL_STEP: c := _RGB(128, 128, 128);
1024 PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT:
1025 case p.LiftType of
1026 LIFTTYPE_UP: c := _RGB(116, 72, 36);
1027 LIFTTYPE_DOWN: c := _RGB(116, 124, 96);
1028 LIFTTYPE_LEFT: c := _RGB(116, 200, 80);
1029 LIFTTYPE_RIGHT: c := _RGB(116, 252, 140);
1030 otherwise c := _RGB(255, 0, 0);
1031 end;
1032 PANEL_WATER: c := _RGB(0, 0, 192);
1033 PANEL_ACID1: c := _RGB(0, 176, 0);
1034 PANEL_ACID2: c := _RGB(176, 0, 0);
1035 otherwise c := _RGB(255, 0, 0);
1036 end;
1037 DrawObject(p.x, p.y, p.width, p.height, c.r, c.g, c.b);
1038 end;
1039 end;
1040 end;
1041 end;
1043 procedure DrawPlayers;
1044 var i: Integer; p: TPlayer; c: TRGB;
1045 begin
1046 if gPlayers <> nil then
1047 begin
1048 for i := 0 to HIGH(gPlayers) do
1049 begin
1050 p := gPlayers[i];
1051 if p.Alive then
1052 begin
1053 case p.Team of
1054 TEAM_RED: c := _RGB(255, 0, 0);
1055 TEAM_BLUE: c := _RGB(0, 0, 255);
1056 otherwise c := _RGB(255, 128, 0);
1057 end;
1058 DrawObject(p.obj.x, p.obj.y, p.obj.rect.width, p.obj.rect.height, c.r, c.g, c.b);
1059 end;
1060 end;
1061 end;
1062 end;
1064 function DrawMonster (m: TMonster): Boolean;
1065 begin
1066 result := false; // don't stop
1067 if m.alive then
1068 DrawObject(m.obj.x, m.obj.y, m.obj.rect.width, m.obj.rect.height, 255, 255, 0);
1069 end;
1071 begin
1072 r_Draw_FillRect(x, y, (x + gMapInfo.Width) div scale, (y + gMapInfo.Height) div scale, 0, 0, 0, alpha);
1073 DrawPanels(gSteps);
1074 DrawPanels(gLifts);
1075 DrawPanels(gWater);
1076 DrawPanels(gAcid1);
1077 DrawPanels(gAcid2);
1078 DrawPanels(gWalls);
1079 g_Mons_ForEach(DrawMonster);
1080 DrawPlayers;
1081 end;
1083 function GetScreenShotName (AsStats: Boolean): AnsiString;
1084 var dir, date: AnsiString;
1085 begin
1086 result := '';
1087 dir := e_GetWriteableDir(ScreenshotDirs);
1088 if dir <> '' then
1089 begin
1090 if AsStats then
1091 begin
1092 dir := e_CatPath(dir, 'stats'); (* TODO: use e_GetWriteableDir *)
1093 result := e_CatPath(dir, StatFilename + '.png');
1094 end
1095 else
1096 begin
1097 DateTimeToString(date, 'yyyy-mm-dd-hh-nn-ss', Now());
1098 result := e_CatPath(dir, 'screenshot-' + date + '.png');
1099 end;
1100 end;
1101 end;
1103 procedure SaveScreenShot (AsStats: Boolean);
1104 var img: TImageData; typ: GLenum; ok: Boolean; fname: AnsiString;
1105 begin
1106 ok := false;
1107 fname := GetScreenShotName(AsStats);
1108 if fname <> '' then
1109 begin
1110 if (gWinSizeX > 0) and (gWinSizeY > 0) then
1111 begin
1112 Imaging.SetOption(ImagingPNGPreFilter, 5);
1113 Imaging.SetOption(ImagingPNGCompressLevel, 5);
1114 InitImage(img);
1115 if NewImage(gWinSizeX, gWinSizeY, TImageFormat.ifA8R8G8B8, img) then
1116 begin
1117 glReadPixels(0, 0, gWinSizeX, gWinSizeY, GL_RGBA, GL_UNSIGNED_BYTE, img.bits);
1118 if glGetError() = GL_NO_ERROR then
1119 begin
1120 if FlipImage(img) and SwapChannels(img, ChannelRed, ChannelBlue) then
1121 begin
1122 ok := SaveImageToFile(fname, img);
1123 end;
1124 end;
1125 end;
1126 FreeImage(img);
1127 end;
1128 end;
1129 if ok then
1130 g_Console_Add(Format(_lc[I_CONSOLE_SCREENSHOT], [fname]))
1131 else
1132 g_Console_Add(Format(_lc[I_CONSOLE_ERROR_WRITE], [fname]));
1133 end;
1135 procedure r_Render_Draw;
1136 var p1, p2: TPlayer; time: LongWord; pw, ph, i, j: Integer;
1137 begin
1138 if gExit = EXIT_QUIT then
1139 exit;
1141 {$IFDEF ENABLE_SYSTEM}
1142 (* hack: if r_pixel_scale changed, reset menu and other things *)
1143 pw := Round(gWinSizeX / r_pixel_scale);
1144 ph := Round(gWinSizeY / r_pixel_scale);
1145 if (pw <> gScreenWidth) or (ph <> gScreenHeight) then
1146 if assigned(sys_ScreenResize) then
1147 sys_ScreenResize(gWinSizeX, gWinSizeY);
1148 {$ENDIF}
1150 INC(FPSCounter);
1151 time := GetTickCount64();
1152 if time - FPSTime >= 1000 then
1153 begin
1154 FPS := FPSCounter;
1155 FPSCounter := 0;
1156 FPSTime := time;
1157 end;
1159 r_Draw_Setup(gWinSizeX, gWinSizeY, gScreenWidth, gScreenHeight);
1161 glClearColor(0.0, 0.0, 0.0, 0.0);
1162 glClear(GL_COLOR_BUFFER_BIT);
1164 p1 := nil;
1165 p2 := nil;
1166 if gGameOn or (gState = STATE_FOLD) then
1167 begin
1168 if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
1169 begin
1170 if gRevertPlayers then
1171 begin
1172 p1 := gPlayer2;
1173 p2 := gPlayer1;
1174 end
1175 else
1176 begin
1177 p1 := gPlayer1;
1178 p2 := gPlayer2;
1179 end;
1180 end
1181 else if gPlayer1 <> nil then
1182 begin
1183 p1 := gPlayer1;
1184 end
1185 else if gPlayer2 <> nil then
1186 begin
1187 p1 := gPlayer2;
1188 end;
1189 if (gSpectMode = SPECT_PLAYERS) and (gPlayers <> nil) then
1190 begin
1191 p1 := GetActivePlayer_ByID(gSpectPID1);
1192 if p1 = nil then
1193 p1 := GetActivePlayer_ByID(GetActivePlayerID_Next());
1194 if gSpectViewTwo then
1195 begin
1196 p2 := GetActivePlayer_ByID(gSpectPID2);
1197 if p2 = nil then
1198 p2 := GetActivePlayer_ByID(GetActivePlayerID_Next());
1199 end;
1200 end;
1201 end;
1203 if gGameOn or ((gState in [STATE_FOLD]) and (EndingGameCounter < 255)) then
1204 begin
1205 if gSpectMode = SPECT_MAPVIEW then
1206 begin
1207 r_Render_DrawMapView(0, 0, gScreenWidth, gScreenHeight, gSpectX + gScreenWidth div 2, gSpectY + gScreenHeight div 2);
1208 end
1209 else if (p1 <> nil) and (p2 <> nil) then
1210 begin
1211 r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight div 2 - 2, p1);
1212 r_Render_DrawPlayerView(0, gScreenHeight div 2 + 2, gScreenWidth, gScreenHeight div 2, p2);
1213 end
1214 else if p1 <> nil then
1215 begin
1216 r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, p1);
1217 end
1218 else if p2 <> nil then
1219 begin
1220 r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, p2);
1221 end;
1223 if gShowMap then
1224 r_Render_DrawMiniMap(0, 0, 160);
1226 {$IFDEF ENABLE_HOLMES}
1227 r_Holmes_Draw;
1228 {$ENDIF}
1230 if MessageText <> '' then
1231 r_Common_DrawFormatText(MessageText, (gScreenWidth - 196) div 2, gScreenHeight div 2, 255, menufont, TBasePoint.BP_CENTER);
1233 if IsDrawStat or (gSpectMode = SPECT_STATS) then
1234 r_Render_DrawStats;
1236 if gSpectHUD and (gChatShow = false) and (gSpectMode <> SPECT_NONE) and (gSpectAuto = false) then
1237 r_Render_DrawSpectHud;
1238 end;
1240 if gPauseMain and gGameOn {$IFDEF ENABLE_MENU}and (g_ActiveWindow = nil){$ENDIF} then
1241 begin
1242 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1243 r_Common_DrawText(_lc[I_MENU_PAUSE], gScreenWidth div 2, gScreenHeight div 2, 255, 255, 255, 255, menufont, TBasePoint.BP_CENTER);
1244 end;
1246 if not gGameOn then
1247 begin
1248 // TODO F key handle
1249 case gState of
1250 STATE_NONE: (* do nothing *) ;
1251 STATE_MENU:
1252 begin
1253 r_Common_DrawBackground(GameWad + ':TEXTURES/TITLE');
1254 {$IFDEF ENABLE_MENU}
1255 if g_ActiveWindow <> nil then
1256 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1257 {$ENDIF}
1258 end;
1259 STATE_FOLD:
1260 begin
1261 if EndingGameCounter > 0 then
1262 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, MIN(MAX(255 - EndingGameCounter, 0), 255));
1263 end;
1264 STATE_INTERCUSTOM:
1265 begin
1266 if gLastMap and (gGameSettings.GameMode = GM_COOP) then
1267 if EndPicPath <> '' then
1268 r_Common_DrawBackground(EndPicPath)
1269 else
1270 r_Common_DrawBackground(GameWad + ':TEXTURES/' + _lc[I_TEXTURE_ENDPIC])
1271 else
1272 r_Common_DrawBackground(GameWad + ':TEXTURES/INTER');
1274 r_Render_DrawCustomStats;
1276 {$IFDEF ENABLE_MENU}
1277 if g_ActiveWindow <> nil then
1278 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1279 {$ENDIF}
1280 end;
1281 STATE_INTERSINGLE, STATE_INTERTEXT, STATE_INTERPIC:
1282 begin
1283 if EndingGameCounter > 0 then
1284 begin
1285 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, MIN(MAX(255 - EndingGameCounter, 0), 255));
1286 end
1287 else
1288 begin
1289 r_Common_DrawBackground(GameWad + ':TEXTURES/INTER');
1290 r_Render_DrawSingleStats;
1291 {$IFDEF ENABLE_MENU}
1292 if g_ActiveWindow <> nil then
1293 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1294 {$ENDIF}
1295 end;
1296 end;
1297 STATE_ENDPIC:
1298 begin
1299 if EndPicPath <> '' then
1300 r_Common_DrawBackground(EndPicPath)
1301 else
1302 r_Common_DrawBackground(GameWad + ':TEXTURES/' + _lc[I_TEXTURE_ENDPIC]);
1303 {$IFDEF ENABLE_MENU}
1304 if g_ActiveWindow <> nil then
1305 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1306 {$ENDIF}
1307 end;
1308 STATE_SLIST:
1309 begin
1310 r_Common_DrawBackground(GameWad + ':TEXTURES/TITLE');
1311 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1312 r_Render_DrawServerList(slCurrent, slTable);
1313 end;
1314 end;
1315 end;
1317 {$IFDEF ENABLE_MENU}
1318 if g_ActiveWindow <> nil then
1319 begin
1320 if gGameOn then
1321 r_Draw_FillRect(0, 0, gScreenWidth, gScreenHeight, 0, 0, 0, 105);
1322 r_GUI_Draw_Window(g_ActiveWindow);
1323 end;
1324 {$ENDIF}
1326 r_Console_Draw(false);
1328 if DebugSound and gGameOn then
1329 begin
1330 for i := 0 to High(e_SoundsArray) do
1331 for j := 0 to e_SoundsArray[i].nRefs do
1332 r_Draw_FillRect(i + 100, j + 100, i + 100 + 1, j + 100 + 1, 255, 0, 0, 255);
1333 end;
1335 if gShowFPS then
1336 begin
1337 r_Common_DrawText('FPS: ' + IntToStr(FPS), 0, 0, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
1338 r_Common_DrawText('UPS: ' + IntToStr(UPS), 0, 16, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
1339 end;
1341 if gGameOn and gShowTime then
1342 begin
1343 r_Common_DrawText(r_Common_TimeToStr(gTime), gScreenWidth - 4, gScreenHeight - 1, 255, 255, 255, 255, stdfont, TBasePoint.BP_RIGHTDOWN);
1344 end;
1346 // TODO draw profilers
1348 {$IFDEF ENABLE_HOLMES}
1349 r_Holmes_DrawUI;
1350 {$ENDIF}
1352 {$IFDEF ENABLE_TOUCH}
1353 glScalef(1 / r_pixel_scale, 1 / r_pixel_scale, 0);
1354 r_Touch_Draw;
1355 {$ENDIF}
1357 if TakeScreenShot then
1358 begin
1359 SaveScreenShot(false);
1360 TakeScreenShot := false;
1361 end;
1363 (* take stats screenshot immediately after the first frame of the stats showing *)
1364 if gScreenshotStats and (StatShotDone = false) and (Length(CustomStat.PlayerStat) > 1) then
1365 begin
1366 SaveScreenShot(true);
1367 StatShotDone := true;
1368 end;
1370 sys_Repaint;
1371 end;
1373 procedure r_Render_Resize (w, h: Integer);
1374 begin
1375 gWinSizeX := w;
1376 gWinSizeY := h;
1377 gRC_Width := w;
1378 gRC_Height := h;
1379 gScreenWidth := Round(w / r_pixel_scale);
1380 gScreenHeight := Round(h / r_pixel_scale);
1381 end;
1383 procedure r_Render_Apply;
1384 begin
1385 {$IFDEF ENABLE_SYSTEM}
1386 if sys_SetDisplayModeGL(GetInfo()) then
1387 e_LogWriteln('resolution changed')
1388 else
1389 e_LogWriteln('resolution not changed');
1390 sys_EnableVSync(gVSync);
1391 {$ENDIF}
1392 {$IFDEF NOGL_INIT}
1393 nogl_Init;
1394 {$ENDIF}
1395 end;
1397 procedure r_Render_RequestScreenShot;
1398 begin
1399 TakeScreenShot := true;
1400 end;
1402 {$IFDEF ENABLE_GIBS}
1403 function r_Render_GetGibRect (m, id: Integer): TRectWH;
1404 begin
1405 result := r_Map_GetGibSize(m, id);
1406 end;
1407 {$ENDIF}
1409 {$IFDEF ENABLE_GFX}
1410 procedure r_Render_QueueEffect (AnimType, X, Y: Integer);
1411 begin
1412 r_Map_NewGFX(AnimType, X, Y);
1413 end;
1414 {$ENDIF}
1416 {$IFDEF ENABLE_TOUCH}
1417 procedure r_Render_GetKeyRect (key: Integer; out x, y, w, h: Integer; out founded: Boolean);
1418 begin
1419 r_Touch_GetKeyRect(key, x, y, w, h, founded)
1420 end;
1421 {$ENDIF}
1423 {$IFDEF ENABLE_MENU}
1424 procedure r_Render_GetControlSize (ctrl: TGUIControl; out w, h: Integer);
1425 begin
1426 r_GUI_GetSize(ctrl, w, h);
1427 end;
1429 procedure r_Render_GetLogoSize (out w, h: Integer);
1430 begin
1431 r_GUI_GetLogoSize(w, h);
1432 end;
1434 procedure r_Render_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
1435 begin
1436 r_GUI_GetMaxFontSize(BigFont, w, h);
1437 end;
1439 procedure r_Render_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
1440 begin
1441 r_GUI_GetStringSize(BigFont, str, w, h);
1442 end;
1443 {$ENDIF}
1445 procedure r_Render_SetProcessLoadingCallback (p: TProcedure);
1446 begin
1447 r_Common_ProcessLoadingCallback := p;
1448 end;
1450 procedure r_Render_ClearLoading;
1451 begin
1452 r_Common_ClearLoading;
1453 end;
1455 procedure r_Render_SetLoading (const text: String; maxval: Integer);
1456 begin
1457 r_Common_SetLoading(text, maxval);
1458 end;
1460 procedure r_Render_StepLoading (incval: Integer);
1461 begin
1462 r_Common_StepLoading(incval);
1463 end;
1465 procedure r_Render_DrawLoading (force: Boolean);
1466 begin
1467 r_Common_DrawLoading(force);
1468 end;
1470 {$IFDEF ENABLE_HOLMES}
1471 function pmsCurMapX (): Integer;
1472 begin
1473 result := r_holmes.pmsCurMapX();
1474 end;
1476 function pmsCurMapY (): Integer;
1477 begin
1478 result := r_holmes.pmsCurMapY();
1479 end;
1481 function r_Render_HolmesViewIsSet (): Boolean;
1482 begin
1483 result := vpSet;
1484 end;
1485 {$ENDIF}
1487 begin
1488 conRegVar('d_sounds', @DebugSound, '', '');
1489 DebugSound := false;
1490 end.