1 //**************************************************************************
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
10 //** Copyright (C) 1999-2006 Jānis Legzdiņš
11 //** Copyright (C) 2018-2023 Ketmar Dark
13 //** This program is free software: you can redistribute it and/or modify
14 //** it under the terms of the GNU General Public License as published by
15 //** the Free Software Foundation, version 3 of the License ONLY.
17 //** This program is distributed in the hope that it will be useful,
18 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 //** GNU General Public License for more details.
22 //** You should have received a copy of the GNU General Public License
23 //** along with this program. If not, see <http://www.gnu.org/licenses/>.
25 //**************************************************************************
27 #include "widgets/ui.h"
31 # include "net/network.h" /* sorry */
32 # include "client/client.h"
35 #include "psim/p_player.h"
36 #include "server/server.h"
39 int NetLagChart
[NETLAG_CHART_ITEMS
] = {0};
40 unsigned NetLagChartPos
= 0;
44 extern VCvarB draw_lag
;
47 //==========================================================================
51 //==========================================================================
57 //==========================================================================
61 //==========================================================================
63 VFont::StaticShutdown();
67 //==========================================================================
71 //==========================================================================
72 int T_ToDrawerX (int x
) {
73 return GRoot
->ToDrawerX(x
);
77 //==========================================================================
81 //==========================================================================
82 int T_ToDrawerY (int y
) {
83 return GRoot
->ToDrawerY(y
);
87 //==========================================================================
91 //==========================================================================
92 int T_FromDrawerX (int x
) {
93 return GRoot
->FromDrawerX(x
);
97 //==========================================================================
101 //==========================================================================
102 int T_FromDrawerY (int y
) {
103 return GRoot
->FromDrawerY(y
);
107 //==========================================================================
111 //==========================================================================
112 void T_SetFont (VFont
*AFont
) {
113 GRoot
->SetFont(AFont
);
117 //==========================================================================
121 //==========================================================================
122 void T_SetFont (VName fontname
) {
123 if (fontname
== NAME_None
) return;
124 VFont
*f
= VFont::GetFont(VStr(fontname
)); // this doesn't allocate
129 //==========================================================================
133 //==========================================================================
134 void T_SetAlign (halign_e NewHAlign
, valign_e NewVAlign
) {
135 GRoot
->SetTextAlign(NewHAlign
, NewVAlign
);
139 //==========================================================================
143 //==========================================================================
144 bool T_IsFontExists (VName fontname
) {
145 if (fontname
== NAME_None
) return false;
146 return !!VFont::GetFont(VStr(fontname
)); // this doesn't allocate
150 //==========================================================================
154 //==========================================================================
155 void T_DrawText (int x
, int y
, VStr String
, int col
, float alpha
) {
156 GRoot
->DrawText(x
, y
, String
, col
, CR_YELLOW
, alpha
);
160 //==========================================================================
164 //==========================================================================
165 int T_TextWidth (VStr s
) {
166 return GRoot
->TextWidth(s
);
170 //==========================================================================
174 //==========================================================================
175 int T_StringWidth (VStr s
) {
176 return GRoot
->StringWidth(s
);
180 //==========================================================================
184 //==========================================================================
185 int T_TextHeight (VStr s
) {
186 return GRoot
->TextHeight(s
);
190 //==========================================================================
194 //==========================================================================
195 int T_FontHeight () {
196 return GRoot
->FontHeight();
200 //==========================================================================
204 //==========================================================================
205 int T_CursorWidth () {
206 return GRoot
->CursorWidth();
210 //==========================================================================
214 //==========================================================================
215 void T_DrawCursor () {
220 //==========================================================================
224 //==========================================================================
225 void T_DrawCursorAt (int x
, int y
) {
226 GRoot
->DrawCursorAt(x
, y
, GRoot
->GetCursorChar());
230 //==========================================================================
234 //==========================================================================
235 void T_DrawCursorAt (int x
, int y
, int cursorChar
, int cursorColor
) {
236 GRoot
->DrawCursorAt(x
, y
, cursorChar
, cursorColor
);
240 //==========================================================================
244 //==========================================================================
245 void T_SetCursorPos (int cx
, int cy
) {
246 GRoot
->SetCursorPos(cx
, cy
);
250 //==========================================================================
254 //==========================================================================
255 int T_GetCursorX () {
256 return GRoot
->GetCursorX();
260 //==========================================================================
264 //==========================================================================
265 int T_GetCursorY () {
266 return GRoot
->GetCursorY();
270 int T_GetCursorChar () {
271 return GRoot
->GetCursorChar();
276 //**************************************************************************
278 // loader messages and progress bar
280 //**************************************************************************
288 static int currMsgNumber
= 0;
289 static int currMsgType
= OSD_MapLoading
;
291 static int lastPBarWdt
= -666;
292 static double pbarStartTime
= 0.0;
293 static double pbarLastUpdateTime
= 0.0;
294 static double pbarLastLagUpdateTime
= 0.0;
295 static int pbarMaxLagWidth
= 0;
297 int R_OSDMsgColorMain
= CR_FIRE
;
298 int R_OSDMsgColorSecondary
= CR_ORANGE
/*CR_PURPLE*/ /*CR_TEAL*/;
301 //==========================================================================
305 //==========================================================================
306 bool R_IsDrawerInited () {
308 return (Drawer
&& Drawer
->IsInited());
315 //==========================================================================
319 //==========================================================================
320 void R_OSDMsgReset (int type
, bool sendKeepalives
) {
323 if (sendKeepalives
) NET_SendNetworkHeartbeat();
327 //==========================================================================
331 //==========================================================================
332 void R_OSDMsgShow (const char *msg
, int clr
, bool sendKeepalives
) {
333 if (sendKeepalives
) NET_SendNetworkHeartbeat();
335 if (!msg
|| !msg
[0]) return;
336 if (Drawer
&& Drawer
->IsInited()) {
337 T_SetFont(SmallFont
);
338 Drawer
->StartUpdate();
339 T_SetAlign(hcenter
, /*vcenter*/vtop
);
340 // slightly off vcenter
342 switch (currMsgType
) {
344 y
= VirtualHeight
/2+64;
345 if (clr
== -666) clr
= CR_TAN
;
348 y
= 8*T_FontHeight();
349 if (clr
== -666) clr
= CR_ICE
;
350 //GRoot->FillRect(0, y+T_FontHeight()*currMsgNumber, VirtualWidth, T_FontHeight(), 0, 1.0f);
353 if (clr
== -666) clr
= CR_TEAL
;
354 y
= max2(4*T_FontHeight(), VirtualHeight
/2-9*T_FontHeight());
355 //GRoot->ShadeRect(96, y+T_FontHeight()*currMsgNumber, VirtualWidth-96*2, T_FontHeight(), 0.666f);
358 y
+= T_FontHeight()*currMsgNumber
;
359 if (currMsgNumber
== 0) {
360 GRoot
->ShadeRect(96, y
-T_FontHeight(), VirtualWidth
-96*2, T_FontHeight()*3, 0.666f
);
362 GRoot
->ShadeRect(96, y
+T_FontHeight(), VirtualWidth
-96*2, T_FontHeight(), 0.666f
);
364 T_DrawText(VirtualWidth
/2, y
, msg
, clr
);
372 //==========================================================================
376 //==========================================================================
377 bool R_PBarReset (bool /*sendKeepalives*/) {
379 pbarStartTime
= Sys_Time();
380 pbarLastUpdateTime
= 0;
381 pbarLastLagUpdateTime
= 0;
384 return (Drawer
&& Drawer
->IsInited());
392 //==========================================================================
396 //==========================================================================
397 static bool RenderLag () {
398 if (!cl
|| !cl
->Net
) return false;
399 double ctt
= Sys_Time();
400 if (ctt
-pbarLastLagUpdateTime
<= 1.0) return false;
401 pbarLastLagUpdateTime
= ctt
;
402 const int nlag
= clampval((int)((cl
->Net
->PrevLag
+1.2*(max2(cl
->Net
->InLoss
, cl
->Net
->OutLoss
)*0.01))*1000), 0, 999);
403 //const int lag0 = clampval((int)(cl->Net->PrevLag*1000), 0, 999);
404 //const int lag1 = clampval((int)(cl->Net->AvgLag*1000), 0, 999);
406 T_SetAlign(hleft
, vtop
);
409 VStr
s0(va("NET LAG:%3d", nlag
));
410 //VStr s1(va("LAGS :%3d %3d", lag0, lag1));
411 //pbarMaxLagWidth = max(pbarMaxLagWidth, max2(T_TextWidth(s0), T_TextWidth(s1))+4*2);
412 pbarMaxLagWidth
= max2(pbarMaxLagWidth
, T_TextWidth(s0
)+4*2);
413 //GRoot->FillRect(xpos-4, ypos-4, pbarMaxLagWidth, T_FontHeight()*2+4*2, 0, 1.0f);
414 GRoot
->FillRect(xpos
-4, ypos
-4, pbarMaxLagWidth
, T_FontHeight()*1+4*2, 0, 1.0f
);
415 T_DrawText(xpos
, ypos
, s0
, CR_DARKBROWN
); ypos
+= 9;
416 //T_DrawText(xpos, ypos, s1, CR_DARKBROWN); ypos += 9;
422 //==========================================================================
426 //==========================================================================
427 bool R_PBarUpdate (const char *message
, int cur
, int max
, bool forced
, bool sendKeepalives
) {
428 if (sendKeepalives
) NET_SendNetworkHeartbeat();
430 if (forced
&& cur
>= max
&& lastPBarWdt
== -666) return false; // nothing was drawn at all
432 // check if we need to update pbar
433 // when we have drawer, delay first update by 800 msec, otherwise don't delay it
436 if (Drawer
&& Drawer
->IsInited()) {
437 if (lastPBarWdt
== -666) {
438 if (Sys_Time()-pbarStartTime
< 0.8) return false;
444 if (max
< 1) return false; // alas
445 if (cur
< 0) cur
= 0;
446 if (cur
> max
) cur
= max
;
449 if (Drawer
&& Drawer
->IsInited()) {
450 int wdt
= cur
*(Drawer
->getWidth()-PBarHPad
*2)/max
;
451 if (!forced
&& wdt
== lastPBarWdt
) {
452 if (draw_lag
&& cl
&& cl
->Net
) {
453 if (RenderLag()) Drawer
->Update();
457 // delay update if it is too often
458 const double currt
= Sys_Time();
459 if (!forced
&& currt
-pbarLastUpdateTime
< 1.0/30.0) return false;
460 pbarLastUpdateTime
= currt
;
462 Drawer
->StartUpdate();
463 // load progressbar textures
464 static bool texturesLoaded
= false;
465 static int left
= -1, right
= -1, mid
= -1, fill
= -1;
466 if (!texturesLoaded
) {
467 texturesLoaded
= true;
468 left
= GTextureManager
.AddFileTextureChecked("graphics/progbar/progbar_left.png", TEXTYPE_Pic
);
469 if (left
> 0) right
= GTextureManager
.AddFileTextureChecked("graphics/progbar/progbar_right.png", TEXTYPE_Pic
);
470 if (right
> 0) mid
= GTextureManager
.AddFileTextureChecked("graphics/progbar/progbar_middle.png", TEXTYPE_Pic
);
471 if (mid
> 0) fill
= GTextureManager
.AddFileTextureChecked("graphics/progbar/progbar_marker.png", TEXTYPE_Pic
);
473 // which kind of progress bar to draw?
477 tex
= GTextureManager(left
);
479 PBarHPad
-8, Drawer
->getHeight()-PBarVPad
-PBarHeight
, PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
+32,
480 0, 0, tex
->GetWidth(), tex
->GetHeight(), tex
, nullptr, 1.0f
);
482 tex
= GTextureManager(right
);
484 Drawer
->getWidth()-PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
, Drawer
->getWidth()-PBarHPad
+8, Drawer
->getHeight()-PBarVPad
-PBarHeight
+32,
485 0, 0, tex
->GetWidth(), tex
->GetHeight(), tex
, nullptr, 1.0f
);
487 tex
= GTextureManager(mid
);
488 Drawer
->FillRectWithFlatRepeat(
489 PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
, Drawer
->getWidth()-PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
+32,
490 0, 0, /*tex->GetWidth()*/(Drawer
->getWidth()-PBarHPad
)*2, tex
->GetHeight(), tex
);
493 tex
= GTextureManager(fill
);
494 Drawer
->FillRectWithFlatRepeat(
495 PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
, PBarHPad
+wdt
, Drawer
->getHeight()-PBarVPad
-PBarHeight
+32,
496 0, 0, /*tex->GetWidth()*/wdt
, tex
->GetHeight(), tex
);
499 Drawer
->FillRect(PBarHPad
-2, Drawer
->getHeight()-PBarVPad
-PBarHeight
-2, Drawer
->getWidth()-PBarHPad
+2, Drawer
->getHeight()-PBarVPad
+2, 0xffffffff);
500 Drawer
->FillRect(PBarHPad
-1, Drawer
->getHeight()-PBarVPad
-PBarHeight
-1, Drawer
->getWidth()-PBarHPad
+1, Drawer
->getHeight()-PBarVPad
+1, 0xff000000);
501 Drawer
->FillRect(PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
, Drawer
->getWidth()-PBarHPad
, Drawer
->getHeight()-PBarVPad
, 0xff8f0f00);
502 if (wdt
> 0) Drawer
->FillRect(PBarHPad
, Drawer
->getHeight()-PBarVPad
-PBarHeight
, PBarHPad
+wdt
, Drawer
->getHeight()-PBarVPad
, 0xffff7f00);
504 if (draw_lag
&& cl
&& cl
->Net
) RenderLag();
510 double currt
= Sys_Time();
511 if (!forced
&& currt
-pbarLastUpdateTime
< 2.0) return false;
512 pbarLastUpdateTime
= currt
;
513 int prc
= cur
*100/max
;
514 if (!message
) message
= "PROCESSING";
515 GCon
->Logf("%s: %02d%% done (%d of %d)", message
, prc
, cur
-1, max
);